Return an inherited type from a method - vb.net

Suppose I have the following classes defined:
Public Class BaseClass
...
End Class
Public Class DerivedClass
Inherits BaseClass
... Extra Fields, methods, etc ...
End Class
And then, in my code, I have a function with a signature of:
Public Function DoSomething(...) As List(Of BaseClass)
And when I try and return an object of type List(Of DerivedClass) from it, I get the error:
Value of type 'System.Collections.Generic.List(Of BaseClass)' cannot be converted to 'System.Collections.Generic.List(Of DerivedClass)'
I know not all the extra fields of the DerivedClass will be filled, but it would give me what I needed.
Is there a way to do this, or is this just considered bad programming practice? And, if so, what would be the right way to do this?

Have a look at this:
http://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx
Understanding Covariance and Contravariance will clear things up a bit :)
Covariance
Enables you to use a more specific type than originally specified.
You can assign an instance of IEnumerable (IEnumerable(Of Derived) in Visual Basic) to a variable of type IEnumerable.
Example:
IEnumerable<Derived> d = new List<Derived>();
IEnumerable<Base> b = d;
Contravariance
Enables you to use a more generic (less derived) type than originally specified.
You can assign an instance of IEnumerable (IEnumerable(Of Base) in Visual Basic) to a variable of type IEnumerable.
Example:
Action<Base> b = (target) => { Console.WriteLine(target.GetType().Name); };
Action<Derived> d = b;
d(new Derived());
Invariance
Means that you can use only the type originally specified; so an invariant generic type parameter is neither covariant nor contravariant. You cannot assign an instance of IEnumerable (IEnumerable(Of Base) in Visual Basic) to a variable of type IEnumerable or vice versa.

Related

indirection operator of auto_gcroot class

auto_gcroot class does not have public indirection operator(operator*).
However, code sample below has been successfully compiled. Why is so?
auto obj = *(std::static_pointer_cast<const auto_gcroot<Object^>>(pObj))
std::static_pointer_cast returns a std::shared_ptr (In this case, a std::shared_ptr<const auto_gcroot<Object^>>), which does have an operator*.
*std::static_pointer_cast<T>(pObj) is an lvalue of type T, so obj will be a copy of the auto_gcroot<Object^> object stored by the shared_ptr.

ReflectionHelper::assertGetterMethod() conflicts with Construction Heuristics requirement

I have the following:
#CustomShadowVariable(variableListenerRef = #PlanningVariableReference(variableName = "..."))
#Override
public boolean isXyz() {
return xyz;
}
Then I get the following:
java.lang.IllegalStateException: The entityClass (class ...) has a PlanningVariable annotated member (bean property ... on class ...) that returns a primitive type (boolean). This means it cannot represent an uninitialized variable as null and the Construction Heuristics think it's already initialized.
Maybe let the member (...) return its primitive wrapper type instead.
... see I really would change boolean to Boolean, but then I'll get the following:
java.lang.IllegalStateException: The getterMethod (public java.lang.Boolean isXyz()) with a CustomShadowVariable annotation must have a primitive boolean return type (class java.lang.Boolean) or use another prefix in its methodName (isXyz).
It seems that the Construction Heuristics wants a nullable type so it can have a null initialization value, yet when provided with a Boolean object, the reflection helper assertion tries to validate it against the primitive type which fails.
Is this a defect?
Changing the method name to getXyz (full signature: Boolean getXyz()).
I'm only guessing because I don't have an example domain containing such shadow variable at hand. But looking at the ReflectionHelper code, this could be the solution. If that works, I'll try to improve the exception message.

How can I disambiguate '=' symbol in VB.NET, in a lambda function

I am using Dapper to query a flat list of items from a database, into a POCO class as follows:
Public Class Node
Public Property Name As String
Public Property ParentNodeName As String
Public Property Children As IEnumerable(Of Node)
End Class
I am trying to use the accepted answer to this question, in order to create a tree out of the flat list.
The only caveat is that I am using VB.NET.
I have tried it a straightforward port of the C# solution:
nodes.ForEach(Function(n) n.Children = nodes.Where(Function(ch) ch.ParentNodeName = n.Name).ToList)
but it does not compile with the error
Error BC30452 Operator '=' is not defined for types 'List(Of Node)' and 'List(Of Node)'.
The = symbol is interpreted as an equality operator, while I meant to use the assignment operator.
I have pasted the C# code into the telerik converter, and the converted code is:
Private Shared Function BuildTree(ByVal items As List(Of Category)) As IEnumerable(Of Category)
items.ForEach(Function(i) CSharpImpl.__Assign(i.Categories, items.Where(Function(ch) ch.ParentId = i.Id).ToList()))
Return items.Where(Function(i) i.ParentId Is Nothing).ToList()
End Function
Private Class CSharpImpl
<Obsolete("Please refactor calling code to use normal Visual Basic assignment")>
Shared Function __Assign(Of T)(ByRef target As T, value As T) As T
target = value
Return value
End Function
End Class
It uses an helper class to solve this issue, but suggests a refactor to avoid this.
Hence the questions:
Is there a general way to disambiguate equality = and assignment = in VB.NET, without resorting to an helper class and a specific function to assignement
In this specific case, is there a simple refactor I can use to get rid of the issue?
That's because of VB.Net distinction between functions and subroutines.
Instead of
nodes.ForEach(Function(n) n.Children = nodes.Where(Function(ch) ch.ParentNodeName = n.Name).ToList)
use
nodes.ForEach(Sub(n) n.Children = nodes.Where(Function(ch) ch.ParentNodeName = n.Name).ToList)
When you use Function, the lambda expression is expected to return a value; and in your case it looks like it wants to return a boolean.
But you want to use a lambda expression that does not return anything (in your case, you want an assignment), you have to use Sub.

kotlin: wrong inference of nullability in function reference?

i want to choose a validation function for a nullable string:
val aString: String? = ...
val validation
// : KFunction1<CharSequence?, Boolean>
= if (...) Objects::isNull else StringUtils::isNotBlank
isNotBlank is from apache commons. it takes string and returns bool.
when i uncomment explicit type declaration all is good. but when there is no explicit type declared, it infers KFunction1<CharSequence, Boolean> so parameter cannot be null. why?
This is intended behavior. The type to the left of :: is actually the type of the instance you're going to pass to the reference as the first argument, so type inference uses it as the first argument to KFunction1.
If you'd like a reference to be callable on StringUtils? objects, use StringUtils?::isNotBlank, but the StringUtils::isNotBlank reference will only accept non-null StringUtils objects.
Reference

VB.NET Using System.Threading.Volatile.Write on Enum var types

I am in need of performing a volatile write on a variable that is an Enum type derived from Byte, but I am stucked.
This is my (example) code:
Public Class MyOwnClass
Friend Enum MyEnum As Byte
Val1
Val2
End Enum
Private MyEnumVar As MyEnum = MyEnum.Val1
Friend Sub SetMyEnumVar(ByVal value As MyEnum)
System.Threading.Volatile.Write(MyEnumVar, value) 'Error!
End Sub
End Class
Since Threading.Volatile.Write is not provided with a signature with those arguments I get this error
Error 1 Overload resolution failed because no accessible Write can be called without a narrowing conversion:
With the list of all the overloads of the method.
CTyping the first argument is not working, because CType returns a casted value of course not with the same reference as MyEnumVar where the method gets the first parameter abviously ByRef instead.
CObject that would return a reference is also not viable because the method also hasn't got the overload for an object type other than Write(Of T)(T, T) where Tmust be a class type.
So how can I accomplish my purpose?
Thanks.
You can use the Write(Of T) overload where T is the type of Enum.
System.Threading.Volatile.Write(Of [Enum])(MyEnumVar, value)