C # equivalent to VB.NET DirectCast?

Does C # have the equivalent of VB.NET DirectCast?

I know that it has () casts and the 'as' keyword, but they line up to CType and TryCast.

To be clear, these keywords do the following:

CType / () casts : if it is already the correct type, drop it, otherwise find the type converter and call it. If the type converter is not found, call InvalidCastException.

TryCast / "as" keyword : if it is the correct type, produce it, otherwise return zero.

DirectCast If this is the correct type, throw it; otherwise throw an InvalidCastException.

After I stated the above, some people still answered that () is equivalent, so I will further explain why this is not so.

DirectCast only allows you to narrow or expand conversions in the inheritance tree. It does not support conversions in different branches of type (), i.e.:

C # is compiling and running:

//This code uses a type converter to go across an inheritance tree double d = 10; int i = (int)d; 

VB.NET IS NOT A COMPLEX

 'Direct cast can only go up or down a branch, never across to a different one. Dim d As Double = 10 Dim i As Integer = DirectCast(d, Integer) 

Equivalent in VB.NET for my C # code: CType:

 'This compiles and runs Dim d As Double = 10 Dim i As Integer = CType(d, Integer) 
+49
casting c # ctype directcast
Apr 21 '10 at 14:32
source share
11 answers

It looks like the functionality you want is not in C #. Try this though ...

 static T DirectCast<T>(object o, Type type) where T : class { if (!(type.IsInstanceOfType(o))) { throw new ArgumentException(); } T value = o as T; if (value == null && o != null) { throw new InvalidCastException(); } return value; } 

Or, even if it is different from VB, name it like this:

 static T DirectCast<T>(object o) where T : class { T value = o as T; if (value == null && o != null) { throw new InvalidCastException(); } return value; } 
+13
Apr 21 '10 at 15:31
source share

SECOND UPDATE :

OK, the C # method is proposed here, which supposedly does basically what DirectCast does in VB.NET.

 static T DirectCast<T>(object o) where T : class { T value = o as T; if (value == null && o != null) { throw new InvalidCastException(); } return value; } 

Here are the problems with the method described above:

  • It has a where T : class constraint that DirectCast does not support.
  • It puts its argument as System.Object - again, not true for DirectCast (at least not the one I know about).
  • It uses as unnecessarily (which is why it has a class constraint); call (T) o will throw an InvalidCastException if it does not work; why check if the value matches with as , just to throw the same exception that would be thrown if you sent the route (T)o to start?

You can actually rewrite this method to get the same results as DirectCast as follows:

 static T DirectCast<T>(object o) { return (T)o; } 

Funny observation: indeed, this whole method is done by boxing, and then tries to unpack it. In other words, DirectCast<int>(12.0) will really be the same as (int)(object)12.0 (and either throw an exception). Understanding this, the proposed DirectCast<T> method is not needed at all.

Now here is an example of how DirectCast and casting with () are “different” between VB.NET and C #:

VB:

 Dim i As Integer = 12 Dim l As Long = DirectCast(i, Long) ' does not compile ' 

FROM#:

 int i = 12; long l = i; // DOES compile 

OK, so one compiles, the other does not. But look at this code. What is the point of DirectCast when you already know the type of object? . This is not a realistic comparison, because in VB.NET there would never be a reason to call DirectCast as the code above does. (If you want to convert a value of type System.Int32 to a value of type System.Int64 in VB.NET, you should use CLng , not DirectCast .) If there were a variable printed as System.Object there , then it would be worthwhile use DirectCast , and the code below would really be equivalent:

VB:

 Dim i As Integer = 12 Dim o As Object = i Dim l As Long = DirectCast(o, Long) ' compiles, throws an exception ' 

FROM#:

 int i = 12; object o = i; long l = (long)o; // compiles, throws an exception 

Therefore, I affirm that DirectCast in VB.NET, in any scenario in which it makes sense to use it (i.e. when the type of an object is unknown at compile time), is the same as direct style () in C # .




EDIT . Well, I'm ashamed that I published a VB code that did not compile. After reviewing what I said, I withdrew my second answer, but retained the first.

If you refer to the use of DirectCast , where you take an object of an unknown type and try to apply it to the desired type, then this is the same as C # () cast:

VB:

 Dim o As Object = SomeObject() Dim i As Integer = DirectCast(o, Integer) 

FROM#:

 object o = SomeObject(); int i = (int)o; 

This is because if o is entered as System.Object , then operation () in C # will try to unpack it. This will fail if the types do not match exactly; for example, if o is a System.Double box, then (int)o throws an exception, because o must be unpacked as System.Double before it can be converted to System.Int32 (if you do not believe me, try it yourself! )




Note: the following is inaccurate because DirectCast does not perform conversion extensions; anyway, I leave it to posterity.

On the other hand, when working with extension and narrowing conversions, using the () operation in C # does more work than just casting as you indicated (i.e. you can do (int)someDouble ). In this case, DirectCast equivalent to a plain old assignment in C #:

VB:

 Dim i As Integer = 12 Dim l As Long = DirectCast(i, Long) ' does not compile, actually ' 

FROM#:

 int i = 12; long l = i; 
+8
Apr 21 '10 at 16:06
source share

Actually, the compiler simply catches a DirectCast violation if it indicates that the typed variable cannot be converted to another type

These are the actual equivalents:

 double d = 10; int i = (int)d; Dim d As Double = 10 Dim i As Integer = d 

Note the danger of this construct, when you simply simply assign a double to integer in VB.NET, the double will be accidentally reduced to an integer.

While C # programmers get compile-time security by accidentally changing the .NET variable. VB.NET programmers have to struggle to always install DirectCast as a safe programming habit.

These are the actual equivalents:

 // will not compile, cannot convert double to int double d = 10; int i = d; ' will not compile, cannot convert double to int Dim d As Double = 10 Dim i As Integer = DirectCast(d, Integer) 

[EDIT]

@ Dan Tao:

There is no need to use DirectCast in C #, the runtime also prevents loading the long value into integer. This is what csauve claims that C # does not have DirectCast, that DirectCast can prevent the assignment of different types of variables, whereas "because" C # does not have this DirectCast, it will be silent when assigning different types. But, as you can see, this is not the case, C # casting is exactly the same as DirectCast. This will throw an InvalidCastException error:

 long l = 10; object o = l; int i = (int)o; 

This will also cause the same runtime error as above:

 Dim l As Long = 10 Dim o As Object = l Dim i As Integer = DirectCast(o, Integer) 

Now that the “fun” part comes, with VB.NET you need to remember many keywords in order to accomplish something. In C #, if a given keyword can be used in another scenario (for example, in this case with a decrease in the number of variables), they will not invent another keyword just for this to happen.

In C #, you just need to do this:

 long l = 10; object o = l; int i = (int)(long)o; 

In VB.NET, if you really want to drag and drop a variable and want an orthogonal way to execute it, i.e. just remember one keyword, you have to do this:

  Dim l As Long = 10 Dim o As Object = l Dim i As Integer = DirectCast(DirectCast(o, Long), Integer) 

But this does not compile, so how to achieve a reduction to an integer? You must remember the other VB.NET keywords. While in C # it is orthogonal, you use the unbox variable using this construct (typehere) , you also downcast / upcast using the same construct (typehere) . In VB.NET, there is a fundamental disconnect between loading a value from an object and lowering it. Therefore, in VB.NET you must do this:

  Dim l As Long = 10 Dim o As Object = l Dim i As Integer = CType(o, Integer) 



Hmm .. I think csauve confusion stems from reusing C # (typehere) , first it is used for downcasting; secondly, the same constructor (check the first part of this post, object o = l ) is also used to unpack the values ​​from the object, which are believed to have conversion behavior of the safe DirectCast type, they are the same!

This is a slide ...

 long l = 1; int i = (int) l; 

... is not equivalent:

 Dim l As Long = 1 Dim i As Integer = DirectCast(l, Integer) 

If you want to perform downcasting, you must do this:

 Dim l As Long = 1 Dim i As Integer = CInt(l) ' can also use CType 

Now, if the VB.NET programmer is intentionally programming and not sleeping during encoding, why will he use DirectCast when he is fully aware that he cannot assign different types? If what VB.NET programmer really wanted was a suppression, he should not try to use DirectCast first. Now the VB.NET programmer, having discovered that DirectCast cannot be used for downcasting, must undo what he wrote and replace it with CInt (or CType)

+1
Apr 21 '10 at 15:59
source share

You can implement it yourself:

 static T CastTo<T>(this object obj) { return (T)obj; } 

Used as follows:

 3.5.CastTo<int>(); //throws InvalidCastException. 

This works and does not include custom converters because the generic files are "allowed" at runtime, but type conversions are solved at compile time - the structure does not actually generate different implementations for each T but rather uses an implementation for a similar T , and therefore, the runtime has no information to allow user transformations.

+1
Apr 21 '10 at 16:01
source share

VB.NET:

 Dim xxx as label = Directcast(sender, label) 

FROM#:

 label xxx = (label)sender; 
+1
Aug 28 '19 at 18:14
source share

You have two types of translation in C #. Without additional code, the equivalent of the DirectCast keyword in C #. The closest thing you don't create yourself is to use () .

You have:

 My_Object c = (My_Object)object 

and

 My_Object c = object as My_Object 

In the first case, if the failure is performed, it throws an error. You say: "I know what this object is, and if not, then something is wrong."

In the second, c to null where possible (null cannot be assigned to value types). In this you say: "I think I know what it is, but if I’m not mistaken, because nothing can be wrong."

Another post explaining casting:

What is the difference between an explicit and an implicit cast type?

0
Apr 21 2018-10-21T00:
source share

Did you really try to run the sample code?

Concerning...

 //This code uses a type converter to go across an inheritance tree string s = "10"; int i = (int)s; 

... you believe that it will work. It also does not work

0
Apr 21 '10 at 15:28
source share

Let me try to take a picture.

First, let me clarify this. This MUST compile:

 //This code uses a type converter to go across an inheritance tree string s = "10"; int i = (int)s; 



VB CType

In VB you should use:

 Dim s as String = "10" Dim i as Integer = CType(s, Integer) 

In C #, I would use:

 string s = "10"; int i = Convert.ToInt32(s); 



VB DirectCast

If it is the correct type, throw it; otherwise throw an InvalidCastException.

Direct casting can only increase or decrease branches, never moving on to another one.

From this explanation, it will be the direct equivalent of C # cast. However, in C #, you will need to specify a translation operator only for discarding. Casting is completely optional. Example:

 // casting down object t = "some random string needing to be casted down"; string s = (string) t; // casting up object a = s; // explicitly casting up although it totally optional object b = (object) s; 

C # cast is not looking for any type converter. It will only look for a specific explicit / implicit operator overload for the type you are trying to execute.




VB TryCast

You correctly understood that this is equivalent to the C # keyword.

0
Apr 21 '10 at 15:42
source share

I think this scenario is best suited because DirectCast has a false idea of ​​compile-time type security checking for the type of non-object objects and is intended only to be back.

 float f = 10; long l = f; Option Strict On Dim f As Single = 10 Dim l As Long = f 

A C # encoder, upon detecting that a float cannot be assigned for a long time and will not compile, will do the following:

 long l = (long)f; 

It is right.

Now, back to our VB.NET encoder, after finding that the float is not assigned for a long time and does not compile, it will try to do this:

 Dim l As Long = DirectCast(f, Long) 

In a few seconds ...

VB.Net Programmer: "Please let me make my suggestions, please compile, please ... !!!"

After a few moments via GoogleDu and MSDN:

VB.NET programmer: "Ah ... so I need to use this CLng or CType construct to cast variables"

 Dim l As Long = CLng(f) 

This is what I meant by DirectCast, it has a false impression of the security of compilation type checking. DirectCast just has to be the opposite if the programmer does not know when and where to use them. DirectCast is a protective blanket that does not wear all the time.

How useful is DirectCast in this scenario if it will not be used in the end?




[EDIT]

@Jules

I do not claim that all VB.NET programmers do not know what the real use of DirectCast is, some of them really know that DirectCast is only for use with object types (and primitive types, objects).

One scenario is when VB.NET encoding, which encodes existing C # code, to VB.NET comes to an erroneous conclusion, with the expected (whether correct or not) language symmetry to each other.

When he sees this construct in code ...

 TextBox txt = (TextBox)sender; 

... He will translate this:

 Dim txt As TextBox = DirectCast(sender, TextBox) 

It is right.

Now, since we programmers love symmetry, some of us (maybe me too, if I don’t know CLng) will try to convert this code ...

 /* numbers are stored in file as float(component file structure is designed by 3rd party company) */ float f = file.ReadFloat(0); long l = (long)f; // but we don't care about using the fractional part 

... to that:

 Dim f As Single = file.ReadFloat(0) Dim l As Long = DirectCast(f, Long) 

If the C # person is the one who will convert the C # code to VB.NET, he will be disappointed with the apparent lack of symmetry here.

But for the person VB.NET, who is tasked with converting C # code to VB.NET, he will get the impression that the C # compiler does not catch incompatible type assignments, but VB.NET catches it. Now, for this obvious discovery, the VB.NET feature for his colleagues and some forums boasts.

But so that the VB.NET programmer is not mistaken in mistakenly determining the intent of the first code. The C # code snippet above began its life as follows: it was originally written as follows:

 float f = file.ReadFloat(0); long l = f; 

And this will not compile, the C # compiler catches incompatible type assignments, in the same way that the equivalent VB.NET with Option Strict On also not compile this (although it will not compile when Option Strict set to On , too soft) . Therefore, we need to use the (long) type float for long use. Becomes as follows: long l = (long)f;

Now, in order to pour one type of variable into another compatible type, in the same spirit that we will convert to this code ...

 TextBox txt = (TextBox)sender; 

... to this code:

 Dim txt As TextBox = DirectCast(sender, TextBox) 

We must convert this code ...

 long l = (long)f; // will compile 

... to this code:

 Dim l As Long = DirectCast(f, Long) ' will not compile 

But alas, this will not be compiled when casting between compatible primitive types, in which case DirectCast is shortened. It does not offer any symmetry to the C # code described above; it cannot be used for primitive primitive types, despite its name Direct Cast .

As I see it, DirectCast should be called CastObject , since it can only use object types (as well as primitive types placed in an object). DirectCast really does not have a business with the assignment of compatible primitive types (integer, double and their lower and higher counterparts). When assigned between compatible primitive types, DirectCast is no longer useful, especially if you somehow move it and replace it with a suitable one.

Or in another way I see this, the DirectCast construct should be changed so that it can display compatible types, for example, like older and newer languages, since then, for example, C, C ++, C #, Java, Delphi, D, etc. .d. Having done this, he will offer significant VB.NET symmetry for other languages ​​when it comes to type casting. By doing this, we can also throw away (hypothetically only, we cannot make other programs fail by relying on old functions), the whole set of functions whose names are not directly mapped to its types (for example, CInt, CDbl, CSng, etc. .), We will use DirectCast instead.

0
Apr 21 '10 at 19:01
source share

DirectCast and () do not always generate the same IL, so I think this is the difference between VB and C # compilers.

AFAICT, reference types are castclass using the castclass IL castclass , whereas for value types the compiler generates the corresponding IL depending on the input types.

In C #, casting from double to integer emits the IL conv.i4 instruction, which will be fun to overwrite the signed bit or anything else in the output if the value is too large. In VB, this is a compilation error.

Interestingly, if you use the intermediate variable object to store double, then the cast will fail for both C # and VB ... but at runtime. Both compilers issue an unbox instead of trying to perform the conversion.

0
Sep 19 '18 at 8:16
source share

Casting () should be the same; it throws an InvalidCastException. Just try this in C #:

  string t = "hello"; object x = t; int j = (int) x; 
-one
Apr 21 2018-10-21T00:
source share



All Articles