Can I include a Generic type parameter in a lamba expression? (VB.NET 2010) - vb.net

(Not really sure if I phrased the question correctly...)
I want to create a lambda expression that would take an Object, attempt to convert it to a passed-in Type, and print to the console whether it was successful or not.
At a glance, the lambda expression may seem a pretty silly way to accomplish this task, but I'd really like to know what I'm doing wrong, so I can better grow my skill set.
VS gives me a designer error about the second "T" in the expression below, telling me it isn't defined)
This is where I left off:
Sub MyMethod(ByVal param as Object)
Dim quickMethod = Sub (Of T)(o as Object)
Console.WriteLine(TryCast(o, T) IsNot Nothing)
End Sub
quickMethod(Of myClass1)(param)
quickMethod(Of myClass2)(param)
quickMethod(Of myClass3)(param)
quickMethod(Of myClass4)(param)
'further logic below... ;)
End Sub

I can't speak for VB specifically, but I'm not aware of any such concept in .NET delegates in general. While a delegate type can be generic, I don't believe you can leave a particular delegate instance "open" in a type parameter, to be provided by the caller. It's an interesting idea though.
Of course, you could easily write a generic method to do this, and that's probably the right way to go. It's an interesting situation where you could have a single-method interface expressing the desired functionality, but you can't express that as a delegate type. Hmm. Just for the sake of discussion, the interface could be something like this:
interface IConverter
{
bool IsConvertible<T>(object input);
}

Related

VB.NET Lambda Does Not Call Method

I'm currently writing a wrapper object for a series of database result sets. In so doing, I've noticed a problem when querying with LINQ and Lambda expressions. Specifically, calling a method within the lambda seems to always make the result set empty and never actually fires the method I'm attempting to filter with. Here's the code:
' Query and filter container results
Public Function [Filter](pFilter As IFilter(Of T)) As System.Linq.IQueryable(Of T)
' THIS YIELDS AN EMPTY SET EVEN WHEN pFilter.Test(o) ALWAYS RETURNS TRUE
Dim lResult As System.Linq.IQueryable(Of T) = mTable.Where(Function(o As T) pFilter.Test(o))
Return lResult
End Function
pFilter implements IFilter with this signature:
Public Interface IFilter(Of T)
Function Test(ByVal pObject As T) As Boolean
End Interface
I've break pointed pFilter.Test(o) and found it is never actually called. Oddly enough, if I replace pFilter.Test(o) with True, I receive the entire table of records as expected. Also, I receive no compile time or run time errors in any case.
I'm pretty new to Lambdas and LINQ so fully recognize I may not understand the limits of what I am attempting to accomplish. Any help is greatly appreciated!
SOLUTION:
I've marked a solution already as the author got me on the right track. The true nature of this problem stems from my attempting to force a .NET function into something LINQ could turn into an SQL statement (which is impossible). To solve this, I've changed my IFilter to return System.Linq.Expressions.Expression(Of Func(Of T, Boolean)) for the Test method. Now I can create strongly-typed filters which return predicates and pass them directly to Where() without the use of a lambda expression. I'm also using LinqKit to make this work more easily for those who may be accomplishing similar tasks.
I think I found what your issue is - understanding the concept of IQueryable. Here is what it says in this article: Lazy Loading With The LazyList
IQueryable is the cornerstone of Linq To Sql, and has (what I think)
is a killer feature: delayed execution. IQueryable essentially creates
an Expression for you that you can treat as an enumerable list - and
only when you iterate or ask for a value will the query be executed.
So you probably never used the result, and that's why it was never called. .NET framework only built the expression tree for you, but did not do any processing.
See also: IQueryable vs. IEnumerable.

Why am I having to double cast here?

I have inheritance structure: Foo implements IGraphNode inherits IGraphItem.
Foo, IGraphItem/IGraphNode, and the implementation for IGraphItem/IGraphNode all reside in separate assemblies. I am using an inversion of control container, so the project I'm working in has a reference to the first two (Foo and IGraphItem/IGraphNode), but not the implementation of IGraphItem/IGraphNode. I also have Option Strict on as it is required for this project (turning if off didn't fix the problem). I'm using .NET 3.5.
I am passing a IGraphItem around and I have code that looks like this:
Public Sub ProcessItem(of IGraphItem)(item As IGraphItem)
If TypeOf item Is Foo Then
Dim f1 = CType(item, Foo) 'Compiler error
Dim f2 = DirectCast(item, Foo) 'Compiler error
'This is what I'm currently having to do. It works.
Dim f = CType(CType(item, IGraphNode), Foo)
'Do stuff
End If
End Sub
Any idea why I'm having to do this? I should add that TryCast works, but since we've just confirmed that item's type is Foo, I don't see why I can't DirectCast it. Shouldn't it just let me and throw an exception if I'm wrong? Is there a better way to accomplish what I'm trying to do?
Your original code compiles without a problem, even when target framework is 3.5.
The problem with your current code is that you've defined a generic method whereas IGraphItem is not the type of your interface but the generic type T which can be any type. But it cannot be another type than T and you're trying to cast it to type Foo.
If you would change your method signature to anything else it would work, for instance:
Public Sub ProcessItem(of IGraphItm)(item As IGraphItem)
I assume that you're somehow "shadowing" the type IGraphItem of your interface with the generic type IGraphItem in this method.
It would also work if you would explicitely tell the compiler that item As IGraphItem actually is a item As YourNamespace.IGraphItem.
I'm sure Jon or Eric could explain it better, but maybe it's helpful anyway ;)
This article might answer your question. If not, well, it's an excellent reading anyway.
http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representation-and-identity.aspx

How Do I Create Something 'OF' a Variable's Type?

I have some code like:
Lookup(Of String)("Testing")
Lookup(Of Integer)("Testing")
And both of those Lookups work great. What I'm trying to is call the appropriate LookUp based on the type of another variable. Something that would look like...
Lookup(Of GetType(MyStringVariable))("Testing")
I've tried to Google this but I'm having a hard time coming up with an appropriate search. Can anyone tell me how to do what I want?
You do not specify the full signature for the method that you're calling, but my psychic powers tell me that it is this:
Function Lookup(Of T)(key As String) As T
And you want to avoid having to repeat Integer twice as in the example below:
Dim x As Integer
x = Lookup(Of Integer)("foo");
The problem is that type parameters are only deduced when they're used in argument context, but never in return value context. So, you need a helper function with a ByRef argument to do the trick:
Sub Lookup(Of T)(key As String, ByRef result As T)
T = Lookup(Of T)(key)
End Sub
With that, you can write:
Dim x As Integer
Lookup("foo", x);
One solution to this is to use reflection. See this question for details.
You can't use a dynamic type unless you do runtime compiling, which of course is really inefficient.
Although generics allows you to use different types, the type still has to be known at compile time so that the compiler can generate the specific code for that type.
This is not the way to go. You should ask about what problem you are trying to solve, instead of asking about the way that you think that it should be solved. Even if it might be possible to do something close to what you are asking, it's most likely that the best solution is something completely different.
The VB.NET compiler in VS2008 actually uses type-inference. That means if you are using a generic method, and one of the parameters is of the generic type, then you don't need to specify the generic type in your call.
Take the following definition...
Function DoSomething(Of T)(Target As T) As Boolean
If you call it with a strongly-typed String for Target, and don't specify the generic parameter, it will infer T as String.
If you call it with a strongly-typed Integer for Target, and don't specify the generic parameter, it will infer T as Integer.
So you could call this function as follows:
Dim myResult As Boolean = DoSomething("my new string")
And it will automatically infer the type of T as String.
EDIT:
NOTE: This works for single or multiple generic parameters.
NOTE: This works also for variables in the argument list, not just literals.

How to pass a generic type not having a Interface to a Of T function

I have a following code which works fine
MsgBox(AddSomething(Of String)("Hello", "World"))
Public Function AddSomething(Of T)(ByVal FirstValue As T, ByVal SecondValue As T) As String
Return FirstValue.ToString + SecondValue.ToString
End Function
Now we are redesigning the application to work with parameters of different types which will be provided through XML
<SomeValues>
<Add Param1="Somedata" Param2="SomeData" MyType="String"/>
<Add Param1="Somedata" Param2="SomeData" MyType="MyBusinessObject"/>
</SomeValues>
If I try to provide the following it gives error as Of accepts only type
''''Get DetailsFromXml --- MyType,Param1,Param2
MsgBox(AddSomething(Of Type.GetType(MyType))(Param1,Param2))
How to solve this issue.
Edit
The above example is given to make the question simple. Actual issue is as follows
I am using SCSF of P&P.
Following is per view code which has to be written for each view
Private Sub tsStudentTableMenuClick()
Dim _StudentTableListView As StudentListView
_StudentTableListView = ShowViewInWorkspace(Of StudentListView)("StudentTable List", WorkspaceNames.RightWorkspace)
_StudentTableListView.Show()
End Sub
Now I want to show the views dynamically.
Public Sub ShowModalView(ByVal ViewName As String)
Dim _MasterListView As >>>EmployeeListView<<<<
_MasterListView = ShowViewInWorkspace(Of >>>EmployeeListView<<<)("Employee List", WorkspaceNames.RightWorkspace)
_MasterListView.Show()
End Sub
So the part shown using the arrows above has to be somehow dynamically provided.
The point of generics is to provide extra information at compile-time. You've only got that information at execution-time.
As you're using VB, you may be able to get away with turning Option Strict off to achieve late binding. I don't know whether you can turn it off for just a small piece of code - that would be the ideal, really.
Otherwise, and if you really can't get the information at compile-time, you'll need to call it with reflection - fetch the generic "blueprint" of the method, call MethodInfo.MakeGenericMethod and then invoke it.
I assume that the real method is somewhat more complicated? After all, you can call ToString() on anything...
(It's possible that with .NET 4.0 you'll have more options. You could certainly use dynamic in C# 4.0, and I believe that VB10 will provide the same sort of functionality.)
In .Net generics, you must be able to resolve to a specific type at compile time, so that it can generate appropriate code. Any time you're using reflection, you're resolving the type at run time.
In this case, you're always just calling the .ToString() method. If that's really all your code does, you could just change the parameter type to Object rather than use a generic method. If it's a little more complicated, you could also try requiring your parameters to implement some common interface that you will define.
If all you are doing is ToString, then making the parameters object instead would solve the problem in the simplest way. Otherwise you are going to have to bind the type at run-time, which in C# looks like:
System.Reflection.MethodInfo mi = GetType().GetMethod("AddSomething");
mi = mi.MakeGenericMethod(Type.GetType(MyType));
object result = mi.Invoke(this, new object[] { Param1, Param2 });
Because it involves reflection it won't be fast though... but I assume that's not a problem in this context.

IsNothing versus Is Nothing

Does anyone here use VB.NET and have a strong preference for or against using IsNothing as opposed to Is Nothing (for example, If IsNothing(anObject) or If anObject Is Nothing...)? If so, why?
EDIT: If you think they're both equally acceptable, do you think it's best to pick one and stick with it, or is it OK to mix them?
If you take a look at the MSIL as it's being executed you'll see that it doesn't compile down to the exact same code. When you use IsNothing() it actually makes a call to that method as opposed to just evaluating the expression.
The reason I would tend to lean towards using "Is Nothing" is when I'm negating it becomes "IsNot Nothing' rather than "Not IsNothing(object)" which I personally feel looks more readable.
I find that Patrick Steele answered this question best on his blog: Avoiding IsNothing()
I did not copy any of his answer here, to ensure Patrick Steele get's credit for his post. But I do think if you're trying to decide whether to use Is Nothing or IsNothing you should read his post. I think you'll agree that Is Nothing is the best choice.
Edit - VoteCoffe's comment here
Partial article contents: After reviewing more code I found out another reason you should avoid this: It accepts value types! Obviously, since IsNothing() is a function that accepts an 'object', you can pass anything you want to it. If it's a value type, .NET will box it up into an object and pass it to IsNothing -- which will always return false on a boxed value! The VB.NET compiler will check the "Is Nothing" style syntax and won't compile if you attempt to do an "Is Nothing" on a value type. But the IsNothing() function compiles without complaints. -PSteele – VoteCoffee
You should absolutely avoid using IsNothing()
Here are 4 reasons from the article IsNothing() VS Is Nothing
Most importantly, IsNothing(object) has everything passed to it as an object, even value types! Since value types cannot be Nothing, it’s a completely wasted check.
Take the following example:
Dim i As Integer
If IsNothing(i) Then
' Do something
End If
This will compile and run fine, whereas this:
Dim i As Integer
If i Is Nothing Then
' Do something
End If
Will not compile, instead the compiler will raise the error:
'Is' operator does not accept operands of type 'Integer'.
Operands must be reference or nullable types.
IsNothing(object) is actually part of part of the Microsoft.VisualBasic.dll.
This is undesirable as you have an unneeded dependency on the VisualBasic library.
Its slow - 33.76% slower in fact (over 1000000000 iterations)!
Perhaps personal preference, but IsNothing() reads like a Yoda Condition. When you look at a variable you're checking its state, with it as the subject of your investigation.
i.e. does it do x? --- NOT Is xing a property of it?
So I think If a IsNot Nothing reads better than If Not IsNothing(a)
I agree with "Is Nothing". As stated above, it's easy to negate with "IsNot Nothing".
I find this easier to read...
If printDialog IsNot Nothing Then
'blah
End If
than this...
If Not obj Is Nothing Then
'blah
End If
VB is full of things like that trying to make it both "like English" and comfortable for people who are used to languages that use () and {} a lot.
And on the other side, as you already probably know, most of the time you can use () with function calls if you want to, but don't have to.
I prefer IsNothing()... but I use C and C#, so that's just what is comfortable. And I think it's more readable. But go with whatever feels more comfortable to you.
I'm leaning towards the "Is Nothing" alternative, primarily because it seems more OO.
Surely Visual Basic ain't got the Ain't keyword.
I initially used IsNothing but I've been moving towards using Is Nothing in newer projects, mainly for readability. The only time I stick with IsNothing is if I'm maintaining code where that's used throughout and I want to stay consistent.
Is Nothing requires an object that has been assigned to the value Nothing. IsNothing() can take any variable that has not been initialized, including of numeric type. This is useful for example when testing if an optional parameter has been passed.