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

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)

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.

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.

VB.NET unable to differentiate between overloaded functions

Current version of MVVM Light has a helper function named Set in ObservableObject class that an inheriting ViewModel class can call to both change property value and raise change notification in one call. Together with the new NameOf operator, this makes the boilerplate code of properties much smaller.
The problem however is that the Set function is overloaded and out of the 3 overloads, the following 2 overloads make VB.NET angry:
Protected Function [Set](Of T)(propertyName As String, ByRef field As T, newValue As T) As Boolean
Protected Function [Set](Of T)(ByRef field As T, newValue As T, <CallerMemberName> Optional propertyName As String = Nothing) As Boolean
Now if you have a String type property, VB.NET cannot differentiate as to which overload we are calling.
Overload resolution failed because no accessible '[Set]' is most specific for these arguments:
'Protected Overloads Function [Set](Of String)(propertyName As String, ByRef field As String, newValue As String) As Boolean': Not most specific.
'Protected Overloads Function [Set](Of String)(ByRef field As String, newValue As String, [propertyName As String = Nothing]) As Boolean': Not most specific.
Note that C# can handle this situation easily, by using ref keyword. Also that even though the current situation is related to MVVM Light, the problem itself is generic. I have tried to use named parameters too, but that doesn't help either. Any hints on how this could be solved?
Here again after almost a year. I just found a little workaround that would work in most cases. Instead of calling one of the overloads mentioned in the question, use the third overload:
Protected Function [Set](Of T)(ByRef field As T, newValue As T, <CallerMemberName> Optional propertyName As String = Nothing) As Boolean
The third parameter of this overload is optional and if you skip it in the call, it will use CallerMemberName to assign it a value. Since Set is almost always called from within the property, this approach should work nicely. No other overload takes two parameters, so compiler can resolve it correctly.

Return an inherited type from a method

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.

Initializing an object ByRef

I don't have much experience with VB.NET and although I've searched, I can't find an answer to the following:
Say I have a Dim myVar As MyClass, and then a function in which I intend to initialize it such as Public Sub MyInit(ByRef myVar As MyClass). Attempting to call this method is giving me a null reference error in the compiler, stating that I should initialize the variable first (but I intend to put that functionality in my method!).
Any thoughts in how I could achieve what I'm attempting here?
PS: I reckon it'd make more sense to create an Initialize() method in MyClass, or to make a Public Function MyClassInitialize() As MyClass, but in my particular scenario this is not possible.
If you're just worried about the Variable 'myVar' is passed by reference before it has been assigned a value warning, you can just change the declaration to Dim myVar as MyClass = Nothing.
If you're writing the MyInit sub, you could also turn it into a function that returns an instance of MyClass:
Public Function MyInit() As MyClass
Dim myLocalVar As New MyClass()
'... initialization here
Return myLocalVar
End Function
...
Dim myVar As MyClass = MyInit()