5

I've been coding in VB for quite awhile and I can do plenty in C# and F# as well, but one syntax difference between VB and C# continues to throw me off. I'd Google this, but I'm not sure what to call it exactly. Consider the following examples:

In visual basic I would do this:

Dim Request As HttpWebRequest = HttpWebRequest.Create("www.google.com")

However, when I make what seems to be the "logical" conversion to C#:

HttpWebRequest Request = HttpWebRequest.Create("www.google.com");

I get the implicit type conversion error. After looking at some other code I realized this seems to be the proper way to do this:

HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create("www.google.com");

But I'm not exactly clear on what purpose the additional mention of the HttpWebRequest type in the parenthesis accomplishes. Is this some sort of casting syntax I didn't know about? What's going on here that makes this work, and the direct conversion not?

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
MattB
  • 2,203
  • 5
  • 26
  • 48
  • One easy way to avoid this is to use `var` instead. i.e. `var Request = HttpWebRequest.Create("www.google.com");` – dub stylee Mar 23 '15 at 19:05
  • Can't use var - I need the HttpWebRequest object to set some properties - I can't set .Accept with the WebRequest object that is returned when using var. Good info though. – MattB Mar 23 '15 at 19:08
  • 1
    VB.net does the conversion for you, in the sense that you get a WebRequest back from both methods, just C# doesn't do the conversion for you, that is your responsibility. Mostly i rather use `HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.google.com")` – Icepickle Mar 23 '15 at 19:08
  • Related: [C# HttpWebRequest vs WebRequest](http://stackoverflow.com/questions/896253/c-sharp-httpwebrequest-vs-webrequest) (i.e. it is *not really* a `HttpWebRequest`). – crashmstr Mar 23 '15 at 19:09

5 Answers5

5

For starters, yes, that syntax is an explicit-cast (sometimes called a C-Style cast).

The reason you need it here is pretty simple. The Create method is actually inherited from the WebRequest class, and it returns a WebRequest (not HttpWebRequest) object. Note its lack of existence in HttpWebRequest and the signature of Create

Assigning to a HttpWebRequest variable then requires downcasting, which is never guaranteed to be safe, so you have to explicitly cast it.

Note that the following code would also compile.

WebRequest Request = HttpWebRequest.Create("www.google.com");
BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
  • Thank you, I think that clears it up, and I did notice that the example you provided shakes out fine as well. My issue is I need to set a bunch of properties for the Request object. Accept, Host, etc., and not all of them seem to be available with the WebRequest object. Any advice on a better way to do that here? BTW, might be verboten in the context of a C# discussion, but I SOOO miss using "With" as we do in VB. – MattB Mar 23 '15 at 19:14
  • @MattB Not familiar with that syntax, sorry :( In any case, downcasting is sometimes necessary. I *would* do an `as` check or similar to avoid an exception if you didn't get an `HttpWebRequest` object for some reason, but that's about it. For more than you probably ever wanted to know about as vs casting, see: http://stackoverflow.com/questions/496096/casting-vs-using-the-as-keyword-in-the-clr – BradleyDotNET Mar 23 '15 at 19:16
  • I'll be sure to read over that. Basically `With` allows you to set properties on subsequent lines by specifying your object once without retyping the object name over and over again. In VB I'll use `With Request` and then set something like the method in a tabbed in block on the next line by typing only `.Method = "POST"` rather than typing the full `Request.Method = "POST"`. It's not a big deal, but as far as I can tell C# doesn't have an equivalent. `using` is about as close as it gets, but that's quite a bit different still. – MattB Mar 23 '15 at 19:25
  • @MattB You can do something like that with initializers, but in this context, yeah there's no equivalent I know of for C#. – BradleyDotNET Mar 23 '15 at 19:28
  • Yeah, I've seen it in the context of the initializers, but it seems like that's not an option in this case. – MattB Mar 23 '15 at 19:32
3

As others have said, the HttpWebRequest.Create method does not return an object cast as an HttpWebRequest type. Instead, it returns an HttpWebRequest object cast as its base WebRequest type. As you have discovered, in C#, you are required to explicitly cast the object to the desired type.

Your confusion, however, is that you assume that you don't need to perform the cast operation in VB.NET. The only reason that you don't need to cast in VB.NET is because you have Option Strict Off. If you turned Option Strict On in VB.NET, as you most likely should, then you would be required to perform the cast, just as in C#:

Dim Request As HttpWebRequest = DirectCast(HttpWebRequest.Create("www.google.com"), HttpWebRequest)

This is the compiler error as displayed by Visual Studio when you have Option Strict On:

Option Strict On disallows implicit conversions from 'System.Net.WebRequest' to 'System.Net.HttpWebRequest'.

When you have Option Strict Off, VB.NET will perform the widening conversion for you without any warning. This can be convenient, but it shuts off some of the compiler type-checking which could catch some bugs for you. My rule of thumb is to always turn Option Strict On except in places where you need it Off.

In other words, by turning Option Strict On, as is recommended by most people, VB.NET's type-checking works the same as C#'s. If you don't want to have to cast the object in C#, the you could accomplish similar things by using the var or dynamic keywords, but I wouldn't recommend it in most cases. Type-checking is your friend. The fact that the syntax for type-casting in C# is easier just makes it all the more convenient.

Steven Doggart
  • 43,358
  • 8
  • 68
  • 105
  • I used to turn Option Strict on at all times. In particular when I was learning, and I still recommend it to others that are learning. Having said that, it made some blocks of code much more difficult to read with all the DirectCasts and TryCasts, and the like so I gradually moved away from it. The code we write is generally distributed to a pretty narrow audience, We know each PC is almost exactly identical, and it's typically fairly narrow in scope and tested pretty heavily, so we don't worry about having Option Strict on anymore. But it does have it's place and is great for learning. – MattB Mar 23 '15 at 19:21
  • 1
    There are some instances where turning `Option Strict Off` is valuable, such to avoid lots of reflection code when late-binding to dynamically loaded libraries. I agree that `CType` and `DirectCast` are an inelegant syntax, but I don't think turning `Option Strict Off` just to avoid using cast operators occasionally is a good principle to follow. If you find VB.NET's syntax to be too verbose, that's a good reason to consider switching to a less verbose language, but it's not a good reason to shut off its features just to save yourself a little typing. – Steven Doggart Mar 23 '15 at 19:33
2

HttpWebRequest.Create returns a WebRequest.

HttpWebRequest.Create does happen to return a HttpWebRequest which derives from WebRequest, but compiler doesn't know that it's actually a HttpWebRequest, but it does know that you're trying to put it into a variable of type HttpWebRequest.

That's why you have to explicitly type it.

1

This is due to Option Strict being set to off in your VB project. If you turn it on implicit narrowing conversions will give compilation errors just as it does in C#. And you would have to write the following in VB:

Dim Request As HttpWebRequest = DirectCast(HttpWebRequest.Create("www.google.com"), HttpWebRequest)

Which is equal to C#'s

HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create("www.google.com");
Magnus
  • 45,362
  • 8
  • 80
  • 118
  • I've already accepted another answer and gotten a ton of information that is helpful in addition, but coming from a VB background this is the short, sweet, and completely direct answer that concisely touches on all points. Nicely done, you get an upvote from me! – MattB Mar 23 '15 at 19:28
1

You can use:

var Request = HttpWebRequest.Create("www.google.com") as HttpWebRequest;
Filipe Borges
  • 2,712
  • 20
  • 32
  • Make sure to check `Request` for null afterwards :) – BradleyDotNET Mar 23 '15 at 19:24
  • Yes, it will be null when the cast is not valid. Check for null when using `as` operator. However, in this specific case it will never be null unless a null object was returned by the `create`. – Filipe Borges Mar 23 '15 at 19:31