Value of type <anonymous type> cannot be converted to <anonymous type> - vb.net

I am sure i am doing something terribly wrong, but i should better ask the experts.
At the third line i get the error Value of type <anonymous type> cannot be converted to <anonymous type>
Dim Query = (From c In Db.web Select New With {.AA = c.AA}).ToList
Dim v = New With {.Amount = 108}
Query.Add(v)
What am i missing here?

Because you have named your fields differently (and maybe it has different type as well, I don't know, cause I don't know what type c.AA is), compiler has created different type for v, so you have 2 anonymous classes, with different fields (even if they have same type, but their name differs) and they are not compatible with each other.
I don't know VB.Net well, but something like this:
Dim Query = (From c In Db.web Select New With {.Amount = CInt(c.AA)}).ToList
Dim v = New With {.Amount = 108}
Query.Add(v)
Should solve the problem, at least works in C#.

Anonymous type identity is based not just on the types of the members, but on their names as well. So these two objects are of different types, even though to human eyes they have the 'same' structure:
Dim a = New With { .Name = "Bob" }
Dim b = New With { .Moniker = "Robert" }
So even if c.AA is an Integer, that's not enough for Query and v to be type-compatible.
Obviously your code is distilled from your real problem, so I can't say exactly what you should be doing instead, but perhaps using a named rather than an anonymous type will solve your problem.
This is documented in the VB.NET Spec (from eg version 9.0 here), section 11.10.4 "Anonymous Object-Creation Expressions" (my emphases) :
If two anonymous class creation expressions occur within the same
method and yield the same resulting shape—if the property order,
property names, and property types all match—they will both refer to
the same anonymous class.
Annotation
It is possible that a compiler may choose to unify anonymous types further, such as at the assembly level, but this cannot be relied upon at this time.
By contrast to the annotation, I believe that for C#, the compiler does guarantee anonymous type identity across an assembly when everything matches.

Related

Option Strict and Anonymous Types dont go together?

I have a Linq query that yields anonymous types. However, now I want to work with the parameters of this anonymous type and it does not seem to work.
For Each obj As Object in Query
Dim row As DataRow = obj.parameter
...
Next obj
Now the compiler throws an error on the expression obj.parameter: "Option Strict On disallows late binding". If I understand it right, the compiler doesnt know the parameters of the anonymous type. I tried Option Infer On (and removed As Object), based on Google results, but it didnt help. Which seems to make sense, because it always seems to be a widening conversion to me.
Is there anyway to fix this, or should I just create a custom type?
The code that declares the anonymous type (i.e. the Select part of your LINQ query) must be in the same method as the the code that uses it and the Query variable's declaration must have an inferred type. You cannot access the properties of an anonymous type after it has been cast to an Object since there is no named type to which you can cast it.
So make sure that your LINQ query (or, at least, the part that Selects into a new anonymous type) is in the same method. E.g.
Dim Query = From prod In products
Select prod.Name, prod.Price
For Each obj in Query
Dim name = obj.Name
...
Next obj

VB.NET: Operator '=' is not defined ... for a variable and object of THE SAME TYPE?

Okay, I am TOTALLY confused here. I have a class... say MyClass. It has several properties of another class of my type, say MyHelperClass (along with other properties).
I am doing the following:
Dim inst As MyClass = New MyClass() With {
.p1 = sv1,
.p2 = sv2,
.h1 = getHelperClass(a1),
.p3 = sv3,
.p4 = sv4,
.h2 = getHelperClass(a2),
.p5 = sv5,
...
.pN = svN
}
*where .p# is some property, .sv# is some valid value. .h# is a property of type MyHelperClass and getHelperClass(a#) returns an instance of said class.
Now, I have the odd thing here, where the assignment statement for h1 works perfect. No problems. The assignment statement for h2 however, it is giving me the following blue-squiggle error:
Operator '=' is not defined for types myLib.MyHelperClass and myLib.MyHelperClass.
I just do not get this error at all! I don't even know where to start to figure this out. HELP!
201105.06 0305:
The signature for h1's type is List(Of myLib.Address), where Address is a very basic class with typical address fields (name, address, city, state, zip, etc.). The return type of getHelperClass is also List(Of myLib.Address).
As SSS hinted at in his answer, I would expect = to not work in the "natural" way if I was using it for equality testing on a class without operators, however I am using it as an assignment operator, not equality, which I can't see any problem with. I am expecting the result of getHelperClass to be assigned to h2. But instead it's telling me = is not defined for the type. Is it possible that for some reason, the compiler is interpreting it as =(EQUALS) instead of =(ASSIGN)?
As for commenting out that line and it happening on the first one, I'll need to wait till I'm back in the office tomorrow to check that. Will report back.
Ah, yeah, sorry didn't read your OP properly. The assignment must be being misinterpreted as an comparison. Maybe you are missing a comma? For example in the statement "a = b = c" the first equals sign is an assignment, the second is a comparison.
You need to add the Operator methods to MyHelperClass
e.g.
Public Shared Operator =(byval a as MyHelperClass, byval b as MyHelperClass) As Boolean
...
End Operator
Public Shared Operator <>(byval a as MyHelperClass, byval b as MyHelperClass) As Boolean
...
End Operator
You should also read up on the difference between Reference and Value types.

GetType on generic types

I'm trying register presenters with Windsor using the convention based method but trying to do this in VB.NET, but the problem is it does not want to compile this statement:
Dim type = GetType(AbstractPresenter(Of))
I am getting : Too few type arguments to AbstractPresenter(Of TView, TPresenter)
Which I don't understand because this is a valid statement according to question. Also showing valid in other C# to VB.NET converters when converting typeof(AbstractPresenter<>).
Any ideas?
There are two type arguments, and you need to specify this, just as you would do for multi-dimensional arrays:
Dim type = GetType(AbstractPresenter(Of ,))
Looks weird, but now the compiler knows that AbstractPresenter expects two type arguments.
By the way, C# has the same requirement. So the above would be written as:
var type = typeof(AbstractPresenter<,>);

VB reflection in for each loop

I'm attempting to use an unknown type in a for each loop as per the following code:
private sub ReflectThis(ByVal rawData As Object())
Dim dataType As Type = rawData(0).GetType()
Dim properties As PropertyInfo() = dataType.getProperties()
For Each item As dataType In rawData ''//AAAA
For Each property As System.Reflection.PropertyInfo properties
''//reflected code use here
The issue that I get is on the line marked AAAA. It complains that 'dataType' is not declared, which I take to mean it does not exist as a proper class.
The intent is to call a web service elsewhere, and regardless of which web service I call, use reflection to add the resulting data struct object's information to a database.
What, if any, are the restrictions on doing something like
Dim myObject As variableInstanceOfTypeObjectHere
or am I making a more fundamental error? If I'm right, what are the workarounds, if any?
When you declare a variable "As" a type, that means you know the type at compile time. That lets the compiler check what you're doing with it. In this case, you don't know the type at compile time - you're getting it at execution time. All you know is that each item is an object - so either don't specify the type (as suggested by Joel) or specify it as Object:
For Each item As Object In rawData ''//AAAA
Just don't specify the type:
For Each item in rawData

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()