Is the 'Is' VB.NET keyword the same as Object.ReferenceEquals? - vb.net

Is the Is VB.NET keyword the same as Object.ReferenceEquals?

Yes, it is, unless combined with a TypeOf check.
Quote from MSDN:
The Is operator determines if two
object references refer to the same
object. However, it does not perform
value comparisons. If object1 and
object2 both refer to the exact same
object instance, result is True; if
they do not, result is False.
Is can also be used with the TypeOf
keyword to make a TypeOf...Is
expression, which tests whether an
object variable is compatible with a
data type.
BTW, also note the IsNot operator (which gives the boolean inverse of the matching Is expression):
IsNot is the opposite of the Is
operator. The advantage of IsNot is
that you can avoid awkward syntax with
Not and Is, which can be difficult to
read.

Related

Error Operator '<>' is not defined for types 'System.Diagnostics.Process' and 'System.Diagnostics.Process'

Error: Operator <> is not defined for types System.Diagnostics.Process and System.Diagnostics.Process.
Function With error
Public Shared Function PornesteJocul() As Boolean
Return Process.GetProcessesByName(DatePatch.BinaryName).FirstOrDefault(Function(p) p.MainModule.FileName.StartsWith("")) <> CType(Nothing, Process)
End Function
Thanks.
If you want to compare something to Nothing then just compare it. There's no need to cast Nothing as a specific type. Also, you use = and <> only for value equality. That means for value types (structures) and for some very few reference types where value equality makes sense, e.g. for Strings where you care that two String objects contain the same characters and not whether two references refer to one String object. For reference equality you use Is and IsNot:
Return Process.GetProcessesByName(DatePatch.BinaryName).FirstOrDefault(Function(p) p.MainModule.FileName.StartsWith("")) IsNot Nothing
If what you actually care about is whether or not there is a match though, rather than what that match is, you don't need a comparison:
Return Process.GetProcessesByName(DatePatch.BinaryName).Any(Function(p) p.MainModule.FileName.StartsWith(""))

Exclamation operator?

I'm learning D and have seen a lot of code like this:
ushort x = to!ushort(args[1]);
I assume this casts args[1] to ushort, but what's the difference between this and cast(ushort)?
EDIT: And what other uses does the exclamation mark operator have?
In D,
to!ushort(args[1])
is shorthand for the template instantiation
to!(ushort)(args[1])
and is similar to
to<ushort>(args[1])
in languages like C++/Java/C#.
The exclamation point is to note the fact that it's not a regular argument, but a template argument.
The notation does not use angle brackets because those are ridiculously difficult to parse correctly for a compiler (they make the grammar very context-sensitive), which makes it that much more difficult to implement a correct compiler. See here for more info.
The only other use I know about is just the unary 'not' operation (e.g. false == !true)... I can't think of any other uses at the moment.
Regarding the cast:
cast(ushort) is an unchecked cast, so it won't throw an exception if the value is out of range.
to!ushort() is a checked cast, so it throws an exception if the value is out of range.
The exclamation mark here is not an operator, it is just a token part of the explicit template instantiation syntax (described in detail here).
std.conv.to (docs) is a function template for converting between arbitrary types. It is implemented entirely in the library and has no special support in the language. It has a broader and different scope compared to the cast operator.
The to template takes two type parameters; a "to" type and a "from" type, in that order. In your example, the template is explicitly instantiated with the single type argument ushort for the "to" parameter, and a second type argument string (assuming args comes from the first parameter to main) is automatically inferred from the regular function argument passed to the function (args[1]) as the "from" parameter.
The resulting function takes a string parameter and returns a ushort parsed from that string, or throws an exception if it failed. The cast operator will not attempt this kind of high-level conversion.
Note that if there is more than one explicit template parameter, or that parameter has more than one token in it (ushort is a single keyword token), you must wrap the template parameter list in parentheses:
ushort result;
result = to!(typeof(result))(args[1]);
In this example, typeof, (, result and ) are four separate tokens and the parentheses are thus required.
To answer your last question, the ! token is also used for the unary not operator, unrelated to template instantiations:
bool yes = true;
bool no = !yes; // 'no' is false
You already got two excellent answers by jA_cOp and Merhdad. I just want answer directly to the OP question (what's the difference between this and cast(ushort)?) - The difference is that cast(ushort)args[1] will not work (you cannot cast from a string to an uint just like that), while the to!(type)(param) template knows what to do with the string and how to convert it to the primitive type.

Is there a conditional ternary operator in VB.NET?

In Perl (and other languages) a conditional ternary operator can be expressed like this:
my $foo = $bar == $buz ? $cat : $dog;
Is there a similar operator in VB.NET?
Depends upon the version. The If operator in VB.NET 2008 is a ternary operator (as well as a null coalescence operator). This was just introduced, prior to 2008 this was not available. Here's some more info: Visual Basic If announcement
Example:
Dim foo as String = If(bar = buz, cat, dog)
[EDIT]
Prior to 2008 it was IIf, which worked almost identically to the If operator described Above.
Example:
Dim foo as String = IIf(bar = buz, cat, dog)
iif has always been available in VB, even in VB6.
Dim foo as String = iif(bar = buz, cat, dog)
It is not a true operator, as such, but a function in the Microsoft.VisualBasic namespace.
If() is the closest equivalent, but beware of implicit conversions going on if you have set Option Strict off.
For example, if you're not careful you may be tempted to try something like:
Dim foo As Integer? = If(someTrueExpression, Nothing, 2)
Will give foo a value of 0!
I think the ? operator equivalent in C# would instead fail compilation.
Just for the record, here is the difference between If and IIf:
IIf(condition, true-part, false-part):
This is the old VB6/VBA Function
The function always returns an Object type, so if you want to use the methods or properties of the chosen object, you have to re-cast it with DirectCast or CType or the Convert.* Functions to its original type
Because of this, if true-part and false-part are of different types there is no matter, the result is just an object anyway
If(condition, true-part, false-part):
This is the new VB.NET Function
The result type is the type of the chosen part, true-part or false-part
This doesn't work, if Strict Mode is switched on and the two parts are of different types. In Strict Mode they have to be of the same type, otherwise you will get an Exception
If you really need to have two parts of different types, switch off Strict Mode (or use IIf)
I didn't try so far if Strict Mode allows objects of different type but inherited from the same base or implementing the same Interface. The Microsoft documentation isn't quite helpful about this issue. Maybe somebody here knows it.
If(<expression>, <expressionIfNothing>)
If <expression> evaluates to a reference or Nullable value that is not Nothing, the function returns that value. Otherwise, it calculates and returns <expressionIfNothing> (Intellisense)
This is useful for checking that a particular value exists, and if not replacing it.
Example:
If(cat, dog)
Here, if the cat is not null, it will return cat. If it is null, it will return dog. Most of the time you will be using a ternary operator for this scenario. However, if you do not want to return the value you are testing you will have to use this instead:
If(condition, cat(true), dog(false))

Why use TryCast instead of DirectCast?

When I am trying to cast Object obj to Type T, if it can not be cast then there is something wrong.
And after I cast the object I will be looking for working with the cast object.
Rather I will be expecting to get an exception at the place where I will be casting it than say where I will be using that object.
In this sense, is it better to use DirectCast instead of TryCast?
Or am I missing some other significance of using TryCast?
(For C# developers, TryCast is similar to "as" and DirectCast is the equivalent of normal casting. As Mike pointed out in the comments, "as" works for nullable value types, but TryCast doesn't.)
If the value really should be a T, then DirectCast is indeed the right way to go - it fails fast, with an appropriate error.
TryCast is appropriate when it's legitimate for the target to be the "wrong" type. For instance, to get all the Button controls in a container, you could go through the control collection and try to cast each to Button. If it works, you do something with it - if it doesn't, you move on. (With LINQ you can just use OfType for this purpose, but you see what I mean...)
In my experience direct casting is appropriate more often than TryCast - although with generics I find myself casting a lot less often than I used to anyway.
The only difference between the two is that, a TryCast will return a null if it fails, while a DirectCast will throw an exception.
These has implications on how you can handle your program. Personally I prefer not having to throw an exception if the possibility of an improper cast (e.g., text input boxes for user input being cast into numeric types) is pretty high.
I think the others have mentioned the times when you should and shouldn't perform "safe casting" (where you ensure that the cast can succeed before risking an exception). If your program does need to perform safe casting then the TryCast method saves both you and the program some work.
I wasn't aware of the TryCast() function until today, and I feel like a fool for using the 'bad' method of safely casting.
If you did not know about the TryCast() function then you might end up with something like this:
'' wasteful, the TypeOf and DirectCast calls are redundant
If TypeOf obj Is SomeClass Then
someObj = DirectCast(obj, SomeClass)
'' More code
End If
The problem is that this method actually performs two casts (technically I think they're actually type-checks). Using the TryCast and checking if the result is Nothing eliminates the 2nd cast and saves needless work.
'' efficient, only one cast is ever performed and there are no InvalidCastExceptions thrown
someObj = TryCast(obj, SomeClass)
If someObj IsNot Nothing Then
'' More code
End If
Following this pattern lets you avoid having to handle expensive exceptions, and efficiently cast to the correct type.
If your design mandates that the object passed to you MUST be of type T, then assert (as in Debug.Assert) that the cast succeeds in debug builds and run exhaustive unit tests to prove that your implementation follows your design.
With your design proven and tested, you can perfrom the direct cast knowing that it can never fail.

VB.NET Get underlying system.type from nullable type

I'm attempting to create a dataset based on the properties of an object. For example, I have an instance of a Person class with properties including ID, Forename, Surname, DOB etc. Using reflection, I'm adding columns to a new dataset based on the object properties:
For Each pi As PropertyInfo In person.GetType().GetProperties()
Dim column As New DataColumn(pi.Name, pi.PropertyType)
table.Columns.Add(column)
Next
My problem is that some of those properies are nullable types which aren't supported by datasets. Is there any way to extract the underlying system type from a nullable type?
Thanks.
Here's your answer, in VB. This may be overkill for your purposes, but it also might be useful to some other folks.
First off, here's the code to find out if you're dealing with a Nullable type:
Private Function IsNullableType(ByVal myType As Type) As Boolean
Return (myType.IsGenericType) AndAlso (myType.GetGenericTypeDefinition() Is GetType(Nullable(Of )))
End Function
Note the unusual syntax in the GetType. It's necessary. Just doing GetType(Nullable) as one of the commentors suggested did not work for me.
So, armed with that, you can do something like this... Here, in an ORM tool, I am trying to get values into a generic type that may or not be Nullable:
If (Not value Is Nothing) AndAlso IsNullableType(GetType(T)) Then
Dim UnderlyingType As Type = Nullable.GetUnderlyingType(GetType(T))
Me.InnerValue = Convert.ChangeType(value, UnderlyingType)
Else
Me.InnerValue = value
End If
Note that I check for Nothing in the first line because Convert.ChangeType will choke on it... You may not have that problem, but my situation is extremely open-ended.
Hopefully if I didn't answer your question directly, you can cannibalize this and get you where you need to go - but I just implemented this moments ago, and my tests are all passing.
Nullable.GetUnderylingType(myType)
will return the underlying type or null if it's not a nullable type.
I'm guessing that the problem is recognizing whether the property is nullable or not. In C# you do this with this code:
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
... but I'm not sure what the equivalent of that last clause is in VB.NET.
You can also use the GetGenericParameters() method on that type. myNullableObject.GetType().GetGenericParameters()[0] should give you the type of nullable it is (so Guid, Int32, etc.)
#Mendelt Siebenga: You can only call GetType on the value property if the variable is not set to null; otherwise, you'll get an exception.
What you want to do is use the "GetValueOrDefault" property and call GetType on that, since you are guaranteed it will not be null. Example:
Dim i As Nullable(Of Integer) = Nothing
Dim t As Type = i.GetValueOrDefault().GetType()