1

In trying to convert the following C# code from a tutorial (by hand, since cross-compilers I have tried don't seem to be able to do this):

httpClient = new HttpClient(unrelated args)
{
    DefaultRequestHeaders = 
    { 
        Accept = { MediaTypeWithQualityHeaderValue.Parse("text/json") } 
    }
}

The closest I have been able to get it is:

Dim httpClient As New HttpClient(unrelated args) With
{
    .DefaultRequestHeaders [=[New HttpRequestHeaders]] [With] 
    {
        .Accept = {MediaTypeWithQualityHeaderValue.Parse("text/json") 
    }
}

(where I have tried various combinations of the values in brackets)

No matter what I try, the best I can get is the error

Property DefaultRequestHeaders is ReadOnly.

I have confirmed that .DefaultRequestHeaders and .Accept are ReadOnly in both VB and C#. Apparently C# is able to write to ReadOnly properties at initialization? Is VB not able to do this as well, or is there some nuance of syntax I am missing to be able to do this? Failing being able to set this at initialization, some other way to set the actual value would presumably work; unfortunately, I don't see a constructor that exposes it, so I don't see any other way to accomplish this, though I would also welcome any suggestion along those lines.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
Trevortni
  • 688
  • 8
  • 23
  • In C#, this syntax doesn't set the property; it just sets properties on its value. – SLaks Feb 05 '18 at 21:34
  • I should have also mentioned that I tried setting the Accept property itself directly, both in this construct and separately after initialization. The Accept property is also ReadOnly. – Trevortni Feb 05 '18 at 21:45
  • Yes; that's the same feature. This compiles to `httpClient.DefaultRequestHeaders.Accept.Add(...)` – SLaks Feb 05 '18 at 21:45

3 Answers3

2

I have confirmed that .DefaultRequestHeaders and .Accept are ReadOnly in both VB and C#. Apparently C# is able to write to ReadOnly properties at initialization?

Nope. C# cannot write to read-only properties any more than VB can. But read-only properties can return an object that can be written to.

What you are looking at are C# collection initializers. They allow you to create collections in one line without having to call Add again and again.

VB also has collection initialzers, but the syntax is very different. That said, it is not 100% necessary to do it that way, especially if you are only adding a single item to the collection.

Dim httpClient As New HttpClient(args As unrelated) 'Assuming unrelated is a type (not sure)
httpClient.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("text/json"))
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • Thank you for the collection initializers link! Knowing what to call something is half the battle, half the time. I still can't find a syntax that lets me use the collection initializer inside the initializer for the HttpClient, as it still complains that the `.DefaultRequestHeaders` is ReadOnly, but the `Add` method seems to be doing the job. – Trevortni Feb 05 '18 at 22:02
2

Apparently nested object and collection initializers for properties is not supported in VB. There was a discussion in 2011 to support it, but I guess it went no where. The current discussion seems to be from July, 2017:

https://github.com/dotnet/vblang/issues/134

NetMage
  • 26,163
  • 3
  • 34
  • 55
1

I just realized that Accept is a collection. Instead of trying to set the entire collection, I called Add once the variable was created, and it appears to be working now.

Trevortni
  • 688
  • 8
  • 23