This question already has answers here:
Difference between wiring events with and without "new"
(6 answers)
What is the difference between Events with Delegate Handlers and those without? [duplicate]
(4 answers)
Closed 1 year ago.
I have a simple question: what's the advantage of instantiating a C# delegate as opposed to just passing the function reference? What I mean is:
Why do:
Thread t = new Thread(new ThreadStart(SomeObject.SomeMethod));
When you can do:
Thread t = new Thread(SomeObject.SomeMethod);
Both will compile and work in my experience...am I missing something?
As long as the method group SomeObject.SomeMethod has a method with return type void and taking no parameters there is no difference. This is because ThreadStart is defined as a delegate that returns void and takes no parameters and therefore there is an implicit conversion from the method group SomeObject.SomeMethod to ThreadStart. Thus, both are invoking the overload Thread(ThreadStart) of the Thread constructor .
The relevant section of the language specification is §6.6 (Method group conversions).
I have a simple question: what's the advantage of instantiating a C# delegate as opposed to just passing the function reference?
So, just a correction of terminology here. With
class MyObject {
public void SomeMethod() { }
}
MyObject someObject = new MyObject();
the thing denoted by someObject.SomeMethod is a method group. You can just think of it as the set of overloaded methods can that be looked up using the notation someObject.SomeMethod.
The compiler will infer that when you typed the shorter code, you meant the longer code. There's no difference in the ultimate effect. If you want the clarity of the full constructor, you can put it in; if you want the brevity of just the method group, you can allow the compiler to infer the constructor. It's just a stylistic choice.
That's equivalent. Good introductory article on the subject: C# Delegates, Anonymous Methods, and Lambda Expressions – O My!
Related
This question already has answers here:
How can I pass in a func with a generic type parameter?
(4 answers)
Closed 2 years ago.
In my code, I am trying to dynamically resolve which type parameter should be used for a generic method call.
private int FooResolver<T1, T2>(bool condition, Func<int> fooMethod)
{
if (condition)
{
return fooMethod<T1>();
}
return fooMethod<T2>();
}
I have created a wrapper method that takes in both type parameters and decides which one to use based on a condition... However, it seems C# does not allow this behavior. Are there any particular reasons for that? And is there a viable workaround for my code?
EDIT
After seeing the responses, I have decided to defer the type definition to the caller of the handler method:
private int FooResolver(bool condition, Func<int> foo1, Func<int> foo2)
{
if (condition)
{
return foo1();
}
return foo2();
}
...
private int Bar()
{
return FooResolver(myCondition, MyMethod<FirstType>, MyMethod<SecondType>);
}
Delegates aren't abstractions to open generic methods or method-groups; they are an indirection to a specific closed method - i.e. everything is already resolved. You can invoke it, and you can use reflection to find out what it is pointing at, but that's all (caveat: for simplicity I'm talking about delegates in the unicast sense; they are technically multicast, but that detail probably doesn't matter here).
If you want to get hold of a different method in the method-group (things that share the same name), or a different generic parameter usage of the same generic method: you'll need to use reflection to get hold of that. You can't do it directly from the delegate instance.
If you demonstrate the intended usage here, we may be able to offer more guidance on ways to achieve what you are after, but: it probably won't be as simple or direct as you are hoping.
This question already has answers here:
What does the '=>' syntax in C# mean?
(7 answers)
Closed 8 years ago.
so I am looking at this C# method
if (IsInDesignMode)
{
// Only runs in design mode
_dataService.GetMachine(_machines[0].Machine.SerialNumber, (machine, error) => //<-- this is what I am confused about
{
SelectedMachine = new MachineViewModel(machine);
});
}
I understand the if() statement and the SelectedMachine = new MachineViewModel(machine); line.
But I am confused about the commented line.
_dataService calls a GetMachine method passing in _machines[0].Machine.SerialNumber param and (machine, error) => {}. It is not an "equal or less than" statement right?.
It kinda looks like a Javascript code to me...?
Does the method say,
If IsInDesignMode {
dataservice.GetMachine(machine serial number, machine error is new MachineViewModel)
}
Can any one explain what => { } this is? thank you very much!
The part you are asking about is an anonymous method that uses a lambda expression. It is commonly used in callbacks.
When you write this
(machine, error) => { SelectedMachine = new MachineViewModel(machine); }
you are making a function that has no name (and therefore cannot be reused by name, like a regular method). It is very convenient in situations when you need to produce a piece of callable code that needs to be used only once, e.g. in callbacks.
Note that the method does not have to be anonymous: you could make an equivalent named method. However, an since the anonymous method is built in the context of the method where it is used, the variables from the context are available to it. Your anonymous method assigns SelectedMachine, which is probably a property of your class. In the same way, anonymous methods can access local variables as well, which is a very powerful mechanism of combining together a state and a piece of code that operates on it.
To be more precise. It is an Anonymous method using lambda expression.
the sign you are asking '=> { }' is called lambda expression.
Usually it is used with Delegate type like func, Action, predicate and others.
Have a look on the above types to make yourself more clear.
It is a lambda expression. Have a look on this page for more info: http://msdn.microsoft.com/en-us/library/bb397687.aspx
This question already has answers here:
Method overload resolution with regards to generics and IEnumerable
(2 answers)
Closed 8 years ago.
So, I'm having an issue with similar code to below:
public static String MyFunc<T>(this IEnumerable<T> list) where T : struct
{
... some code ...
return myString;
}
public static String MyFunc<T>(this T o) where T : struct
{
... some code ...
return myString;
}
The problem is that when trying to do call MyFunc on a List it uses the second function instead of the one that accepts an IEnumerable. I know this has to do with variance, but I'm uncertain as to how to force it to use the first function rather than the second. The code I would use to call the first one would be:
List<int> x = new List<int>();
String s = x.MyFunc();
The above code immediately goes to the second function and I need it to use the first. How can I force the desired behavior? Incidentally, I'm using .NET 4.0
The reason that it's currently picking the second method is that a conversion from a type to itself (second method, T=List<int>, conversion from List<int> to List<int>) will always be "better" than a conversion to the type it implements (first method, T=int, conversion from List<int> to IEnumerable<int>). This has nothing to do with variance, by the way - it's just the method overloading algorithm and type inference.
Note that with your current code, although the second overload is picked, it will then be found to be invalid because T violates the T : struct constraint. The constraint is only checked after the overload is chosen. See Eric Lippert's blog post on this for more details.
I suggest you just give the two methods different names.
EDIT: As noted by Anthony in comments, this can work if you call it as:
x.AsEnumerable().MyFunc();
Or just change the declaration to:
IEnumerable<int> x = new List<int>();
x.MyFunc();
It's not entirely clear to me exactly why it's better here - in this case after type argument substitution, you've basically got IEnumerable<T> as the parameter type in both cases. However, I would still strongly recommend using different names here. The fact that it's got me puzzling over the spec to work out which overload is being called should be enough indication that the behaviour won't be immediately clear to everyone reading the code.
EDIT: I think the reason is here (from the C# 5 spec, section 7.5.3.2):
A type parameter is less specific than a non-type parameter
So just T is less specific than IEnumerable<T>, even though the latter involves a type parameter. It's still not clear to me whether this is the language designers' intended behaviour... I can see why a type which involves type parameters should be seen as less specific than a type which doesn't involve type parameters, but not quite this wording...
This question already has answers here:
Compiler Ambiguous invocation error - anonymous method and method group with Func<> or Action
(4 answers)
Closed 9 years ago.
Please consider the following code:
class Program
{
static void Foobar() { }
static void Test(Action a) { }
static void Test(Func<bool> a) { }
static void Main(string[] args)
{
Test(Foobar);
}
}
It does not compile on VS2012. The compiler complains, that the reference to the method Foobar in the line Test(Foobar) is ambigious. This is the whole error message I get:
The call is ambiguous between the following methods or properties:
'Program.Test(System.Action)' and 'Program.Test(System.Func<bool>)'
Now, the fix would be to just cast Foobar into an Action to force the correct overload: Test((Action)Foobar).
But I am interested in the reason, why C# can't figure this out by himself? Why does he have to think that a Func<bool> would be an valid overload for a void()-function?
I know that you can not overload a method with another method that only differs in its return type. But that does not seem to be the case here. I am not overloading Foobar(). Sure, the return value may not be part of Foobar's signature, but why does this matter when it comes to convertion from method groups into delegates?
I am also aware of the problem, that the compiler sometimes refuses to cast method groups with overloaded methods into specific delegates, even if he could have all the information he needs, but I think that is a different problem (and a different error message). Again - Foobar is not overloaded. Only Test() is.
Edit: As Matthew pointed out, the problem is the same as the linked question. However, I am not 100% satisfied with the (very good) answer that Eric Lippert and Jon Skeet gave there.
In one part of his answer, Eric says:
The principle here is that determining method group convertibility requires selecting a
method from a method group using overload resolution, and overload resolution does
not consider return types.
Any clue why is that? To me, it seems that a solution to the problem is exactly to change this sentence above and also consider the return type when choosing methods from a method group. Period, finished and everyone is happy, no? ;)
A practical example why this ambigious error sucks is, that Task.Run() can not be used on void()-methods of the own class without a cast. So even in some MSDN examples I saw, they used Task.Run(() => Foobar()) instead of the much cleaner Task.Run(Foobar).
Because both delegates could be called without any parameter:
Action action = new Action(() => ...);
Func<bool> func = new Func<bool>(() => true);
action();
func(); // Legal even if you ignore the return value
The return type is not taken into account to resolve the overload.
This question already has answers here:
LINQ .Cast() extension method fails but (type)object works
(3 answers)
Closed 9 years ago.
I recently had a problem using it user-defined casts (cast operator overload) alongside linq's Cast method.
I found a similar question about my problem here at SO and I also found a link that explains it well. My problem is solved.
But something kept me wondering:
Why this doesn't work:
foolist.Cast<bar>(); // throws InvalidCastException
while this works:
foolist.Select(f => (bar)f).ToList(); // works fine
I believe that it's something related to the implementation of each method. If so, couldn't the Cast method have a similar implementation to Select allowing it to be used with user-defined casts (since this is somewhat expected).
Note: I'm not asking why it fails. I'm asking why the Cast method was written in a way that fails.
The reason why is that the Cast method performs the cast in a generic context
IEnumerable<T> Cast<T>(this IEnumerable e) {
foreach (object cur in e) {
return (T)cur;
}
}
The actual casting logic is verified and emitted at this exact point. This point is in a generic function and has no knowledge of the user defined conversions for the type T is eventually instantiated into. All it has access to is standard CLR style conversions.
In the second example you are doing a cast on the real type (not a generic type parameter). Hence the C# compiler has access to all user defined conversions on that object and can insert the most appropriate one.