In debugging mode, if I hover over a predicate, what I see is just some type names and some non-understandable symbols. This makes it very difficult to debug a code, for example to know what predicate some variable is holding. I usually assign this predicates values using lambda expression. Is there any way to have some idea of what the predicates contain?
For example, if I have a Predicate<object> myPred variable or a List<Predicate<object>> predList variables, how can I debug what value myPred has or what predList contains at runtime?
You probably want Expression<Predicate<T>>. It can be converted to Predicate<T> in order to call it, but retains the information about the lambda structure.
[I haven't checked the C# IDE experience, but actually the VS2010 VB.NET experience.]
Either use Expression as #BenVoigt suggests, or don't use anonymous lambdas for your predicates: (VB.NET answer: Use Functions named by you and specify them with the AddressOf operator.)
C# answer is something like: declare explicit functions named by you and specify the function name when assigning the predicate.
Here is my test VB.NET code that confirms at least one way of dynamically creating predicates can be named successfully. In the VB.NET IDE these are easily seen by name.
Module Module1
Sub Main()
For i = 1 To 2
'Dim p As Predicate(Of Object) = Function(o) (o Is Nothing)
'Dim p As Predicate(Of Object) = AddressOf NamedPredicate
Dim p As Predicate(Of Object) = GeneratePredicate(i)
Dim q As Expressions.Expression(Of Predicate(Of Object)) = Function(o) (o IsNot Nothing)
If p(q) Then Console.WriteLine((q.Compile)(p))
Next
End Sub
Private Function NamedPredicate(ByVal o As Object) As Boolean
Return (o Is Nothing)
End Function
Private Function GeneratePredicate(ByVal i As Integer) As Predicate(Of Object)
Dim gp = New Reflection.Emit.DynamicMethod("DynPred" & i, GetType(Boolean), {GetType(Object)})
Dim mb = gp.GetILGenerator
mb.Emit(Reflection.Emit.OpCodes.Ldarg, 0)
mb.Emit(Reflection.Emit.OpCodes.Ldnull)
mb.Emit(Reflection.Emit.OpCodes.Ceq)
If i = 2 Then
mb.Emit(Reflection.Emit.OpCodes.Ldc_I4_0)
mb.Emit(Reflection.Emit.OpCodes.Ceq)
End If
mb.Emit(Reflection.Emit.OpCodes.Ret)
GeneratePredicate = DirectCast(gp.CreateDelegate(GetType(Predicate(Of Object))), Predicate(Of Object))
End Function
End Module
if you mean that in such example
new List<int>()
.Select(i => i + 1);
you would like to debug i + 1 part then you can put your mouse cursor (caret) somewhere at i + 1 and press F9 that will add a breakpoint in that expression
Related
public static T GetResult<T>(this RpcResponseMessage response, bool returnDefaultIfNull = true, JsonSerializerSettings settings = null)
{
if (response.Result == null)
{
if (!returnDefaultIfNull && default(T) != null)
{
throw new Exception("Unable to convert the result (null) to type " + typeof(T));
}
return default(T);
}
try
I am playing around with Nethereum code. I noticed something very weird. The second parameter of GetResult has type bool. The third one has type JsonSerializerSettings and so on.
But the first argument:
The type is "this"
What the hell?
I thought this in C# is like me in VB.net: it means a pointer to itself. A reference to itself.
So why is the type this?
Perhaps the real type is RpcResponseMessage. But what does the word this state there?
I use Telerik to convert the code to vb.net and I get
Public Shared Function GetResult(Of T)(ByVal response As RpcResponseMessage, ByVal Optional returnDefaultIfNull As Boolean = True, ByVal Optional settings As JsonSerializerSettings = Nothing) As T
If response.Result Is Nothing Then
If Not returnDefaultIfNull AndAlso Nothing IsNot Nothing Then
Throw New Exception("Unable to convert the result (null) to type " & GetType(T))
End If
Return Nothing
End If
Which is weird again. The word this is gone. It's not replaced by me. Also I wonder why we need to add byVal in vb.net? Class is always passed by reference and primitive type is passed by value.
Also, the code is called like this
return response.GetResult<T>();
Whoa!. A static class function is called by an object. I've heard a long time ago that the way object function works is it passes itself as argument to a function. I have never seen it's treated directly like this.
What am I missing?
Where can I learn more about it? What sort of weird syntax is this?
Update: I was aware of what extension method is. I forget. In VB.net it doesn't use me or this. It's done differently in vb.net I am using this convertor to convert vb.net to C#.
https://converter.telerik.com/
I didn't remember if there was <extension()> before or not. This is the new translation
<Extension()>
Public Shared Function GetResult(Of T)(ByVal response As RpcResponseMessage, ByVal Optional returnDefaultIfNull As Boolean = True, ByVal Optional settings As JsonSerializerSettings = Nothing) As T
If response.Result Is Nothing Then
If Not returnDefaultIfNull AndAlso Nothing IsNot Nothing Then
Throw New Exception("Unable to convert the result (null) to type " & GetType(T))
End If
Return Nothing
End If
End Function
The type of argument is RpcResponseMessage.
"This" is added before the type tells the compiler you want to use it as an extension method.
So you can call it like that (without or without "this"):
var response = new RpcResponseMessage();
GetResult<string>(response);
And like that (only with "this"):
var response = new RpcResponseMessage();
response.GetResult<string>();
That is why it's called the "extension method" - it extends the class's functionality without modifying the class.
I want to know on how to error using Tag Property? I have code in VB.Net but I do not know to convert it to C#.
Scenario: The textbox_qty only accepts integers. If the user types a non-numeric character, it shows Tag property saying Invalid Characters.
This is the code I used in VB.Net. I use this if the for has null fields.
Private Function ValidField(ByVal ParamArray ctl() As Object) As Boolean
For i As Integer = 0 To UBound(ctl)
If ctl(i).Text = "" Then
Error_reg.SetError(ctl(i), ctl(i).tag)
Return False
Exit Function
End If
Next
Return True
End Function
If ValidField(TextBox_userName, TextBox_password, TextBox_retypePassword, TextBox_lastName, TextBox_firstName, ComboxBox_group, ComboBox_question, TextBox_answer) = False Then
Exit Sub
If this code does not work? Is there another code that can show error in Tag Property without converting my VB.Net code to C#?
Thank you for helping me!
It may be worthwhile to check into the Information Class, it has methods for validating objects. While it is a VisualBasic class, it can still be used in C# which is one of the main benefits of the .Net Framework.
In Visual Basic you do not need to add any references to your project.
If you want to use the Information Class in C# make sure to add a reference to Microsoft.VisualBasic in your project, then add using Microsoft.VisualBasic; to the class or module that you are adding the following code to.
You can use the Information.IsNumeric method to validate a numeric entry.
Example VB.Net code...
Private Function ValidField(ByVal ParamArray ctl() As Object) As Boolean
For i As Integer = 0 To UBound(ctl)
Dim tB As TextBox = DirectCast(ctl(i),TextBox)
If Not IsNumeric(tB.Text) Then
Error_reg.SetError(tB, tB.Tag)
Return False
End If
Next
Return True
End Function
Example C# code...
private bool ValidField(params object[] ctl)
{
for (int i = 0; i <= Information.UBound(ctl); i++) {
TextBox tB = (TextBox)ctl[i];
if (!Information.IsNumeric(tB.Text)) {
Error_reg.SetError(tB, tB.Tag);
return false;
}
}
return true;
}
Also the Exit Function after the Return statement is not needed, Return automatically exits the function with the result.
First, you can use this converter to convert VB code to C# or vice versa.
Second please tell us where is "textbox_qty" variable in code? Assuming that it is one of parameter to "ValidField" function like this:
ValidField(TextBox_userName, TextBox_password, TextBox_retypePassword, TextBox_lastName, TextBox_firstName, ComboxBox_group, ComboBox_question, TextBox_answer, textbox_qty)
Then solution would be to update "ValidField" as follow:
Private Function ValidField(ByVal ParamArray ctl() As Object) As Boolean
For i As Integer = 0 To UBound(ctl)
If ctl(i).Name = "textbox_qty" AndAlso Not IsNumeric(ctl(i).Text) Then
Error_reg.SetError(ctl(i), ctl(i).tag)
Return False
Exit Function
End If
Next
Return True
End Function
Why does conditional if in VB require not handle the direct cast of the conditions. For example in C# this is just fine...
bool i = false;
i = (1<2)? true:false;
int x = i? 5:6;
But if I wanted the same thing in VB I would have to cast it
Dim i as Boolean = CBool(IIF(1<2, True, False))
Dim x as Integer = CInt(IIF(i, 5, 6))
I don't understand why C# will do the transform and why VB does not. Should I be casting on my C# conditionals eg
bool i = Convert.ToBoolean((1<2)? True: False);
int x = Convert.ToInt32(i? 5:6);
Also, Yes I am aware that IIF returns type object but I would assume that C# does as well as you can return more than just True|False; it seems to me that C# handles the implicit conversion.
IIf is a function and is not equivalent to C#’s ?:, which is an operator.
The operator version has existed for a while in VB.NET, though, and is just called If:
Dim i As Boolean = If(1 < 2, True, False)
… which is, of course, pointless, and should just be written as:
Dim i As Boolean = 1 < 2
… or, with Option Infer:
Dim i = 1 < 2
This code will show you the difference between the IIf function and the If operator. Because IIf is a function, it has to evaluate all of the parameters to pass into the function.
Sub Main
dim i as integer
i = If(True, GetValue(), ThrowException()) 'Sets i = 1. The false part is not evaluated because the condition is True
i = IIf(True, GetValue(), ThrowException()) 'Throws an exception. The true and false parts are both evaluated before the condition is checked
End Sub
Function GetValue As Integer
Return 1
End Function
Function ThrowException As Integer
Throw New Exception
Return 0
End Function
I'm trying to create a class thats holds two (or more) generic delegates as properties. This way I can pass the object to a method and use only one parameter on that method. The problem is that I get a warning to specify a type, but I don't know the type yet. The whole point is to defer type declaration until the object gets instantiated.
Here's some dummy code dummy code to show what I want to do.
Public Function Method1()
Dim _container as Container = new Container()
_container.Property1 = //Here create delegate with type string
_container.Property2 = //Here create delegate with type integer
Method3(_container)
End Function
Public Function Method2()
Dim _container as Container = new Container()
_container.Property1 = //Here create delegate with type Integer
_container.Property2 = //Here create delegate with type integer
Method3(_container)
End Function
Public Function Method3(container as Container)
//execute type specific code and the delegates
//Throw exception when type is not supported (yet)
end Function
public Class Container
Property Property1 as MyDel(of T)
Property Property2 as MyDel(of T)
end Class
Public delegate function Mydel(of T)()
That's it. The point of this being that when adding new information/functionality to the system it is easy to create a new method called Method4, which uses arguments as needed (and of course create the method that will be executed as delegate).
I would like to put two delegates in one class because their is a connection between them and things belonging together should be put together in one class; just like a Person class can hold a name and address.
This code doesn't work, because Container needs a Type T, which means Method3 needs a specific type, but i can't do that because then I can't call Method3 with different arguments as I showed. I tried using a wrapper class, but a type specification is needed all the time.
I know you can do this
Public Property TestProp() As [Delegate]
Get
End Get
Set(ByVal Value As [Delegate])
End Set
End Property
[source:http://www.xtremedotnettalk.com/showthread.php?t=96800]
But that is not generic. What am I missing?
BTW, this is an optimization for code calling Method3 with two arguments. That seemed to work fine. Then I thought trying to use only one argument, which would make the system easier to understand.
My old code looks something like this:
Public function OldMethod1()
Dim del1 as Mydel(of Integer) = AddressOf SomeMethod
Dim del2 as MyDel(of String) = AddressOf SomeOtherMethod
oldMethod3(del1, del2)
end Function
Public function OldMethod2()
Dim del1 as Mydel(of String) = AddressOf AnOtherMethod
Dim del2 as MyDel(of String) = AddressOf AgainSomeOtherMethod
oldMethod4(del1, del2)
end Function
Public Function oldMethod3(del1 as Mydel(of Integer), del2 as Mydel(of string))
//execute delegates
end Function
Public Function oldMethod4(del1 as Mydel(of string), del2 as Mydel(of string))
//execute delegates
end Function
When reading this code I saw that it is only the type of the parameter the determines the execution flow. So if you can determine the subtype of the generic you know what to do. That seemed to be possible (use typeOf and or GetType), so the next thing to do is to create a generic parameter object that could be a substitute for 'del1' (I now realize I took it even took one step further and created the Container class to hold both the parameters).
Any answer in C# or VB.net will do. I use both.
The question is a little confusing, so this may not be an answer, but it's too long for a comment! I think what you want to do is use Action(Of T) as the type for Container.Property1 and Container.Property2.
Something like this (this will run in LINQPad using Language: VB Program):
Sub Main
Dim c1 = New Container(Of String, String)()
c1.Property1 = AddressOf Method1
c1.Property2 = AddressOf Method1
Method3(c1)
Dim c2 = New Container(Of String, Integer)()
c2.Property1 = AddressOf Method1
c2.Property2 = AddressOf Method2
Method3(c2)
End Sub
Public Sub Method1(x As String)
Console.WriteLine("Method1: {0}", x)
End Sub
Public Sub Method2(x As Integer)
Console.WriteLine("Method2: {0}", x)
End Sub
Public Sub Method3(Of T1, T2)(container as Container(Of T1, T2))
Console.WriteLine("Method3 got {0}, {1}", GetType(T1), GetType(T2))
' Not sure how you would actually call the delegates
If GetType(T1) = GetType(String) Then
container.Property1.DynamicInvoke("Hello")
ElseIf GetType(T1) = GetType(Integer) Then
container.Property1.DynamicInvoke(123)
End If
If GetType(T2) = GetType(String) Then
container.Property2.DynamicInvoke("World")
ElseIf GetType(T2) = GetType(Integer) Then
container.Property2.DynamicInvoke(456)
End If
End Sub
Public Class Container(Of T1, T2)
Public Property Property1 As Action(Of T1)
Public Property Property2 As Action(Of T2)
End Class
This produces the following results:
Method3 got System.String, System.String
Method1: Hello
Method1: World
Method3 got System.String, System.Int32
Method1: Hello
Method2: 456
http://msdn.microsoft.com/en-us/library/bb763133.aspx
Module Module1
Sub Main()
Dim array1 As Func(Of Integer)() = New Func(Of Integer)(4) {}
For i As Integer = 0 To 4
array1(i) = Function() i
Next
For Each funcElement In array1
System.Console.WriteLine(funcElement())
Next
End Sub
End Module
It says the result will always be 5 namely the final value of i. How come?
They don't put the iteration variable in the "closure"?
The problem occurs because lambda expressions do not execute when they are constructed but rather when they are invoked.
See the link below:
http://blogs.msdn.com/b/vbteam/archive/2007/07/26/closures-in-vb-part-5-looping.aspx
Hope it helps.