-
Notifications
You must be signed in to change notification settings - Fork 1k
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: Convert delegate types with compatible signature automatically #149
Comments
The fields of the delegate should be identical so this should be cheap in most cases. Multicast would be less cheap. |
Introducing conversions among types that can already exist would be a breaking change to the language, and would therefore be undertaken only if the benefits were overwhelming. I don't see that here. |
@gafter Is it still a breaking change in the case where there's an explicit conversion? if so, can you please elaborate on that? p.s. I wonder whether you refer to nominal vs structural typing in both of these cases of explicit and implicit conversion. |
@eyalsk Why bother with an explicit conversion when you can already write public void Custom_delegates_are_bad()
{
Predicate<string> match1 = value => value == "Blarg";
Func<string, bool> match2 = value => value == "Blarg";
CustomMatchingFunction match3 = value => value == "Blarg";
match1 = match2.Invoke;
match1 = match3.Invoke;
} |
@gafter You're right, thank you. |
@gafter because in this case you cannot pass a delegate as method group if it doesn't exactly of type it is declared in calling method. For example, I really like |
Chaining delegate calls using public static T Cast<T>(this Delegate @delegate) where T : class
{
if (@delegate == null) return null;
var multicastList = (@delegate as MulticastDelegate)?.GetInvocationList();
if (multicastList != null)
{
switch (multicastList.Length)
{
case 0:
return null;
case 1:
if (multicastList[0] != @delegate)
return multicastList[0].Cast<T>();
break;
default:
var convertedItems = new Delegate[multicastList.Length];
for (var i = 0; i < multicastList.Length; i++)
convertedItems[i] = (Delegate)(object)multicastList[i].Cast<T>();
return (T)(object)Delegate.Combine(convertedItems);
}
}
return (T)(object)Delegate.CreateDelegate(typeof(T), @delegate.Target, @delegate.Method, true);
} Only thing that would be better is |
But we have a lot of reflection here, especially that you don't have compile-time checks, and still able to cast |
@Pzixel You do get compile-time checks when you chain delegate calls together via |
@jnm2 that's exactly what I am talking about |
@gafter I was attempting to communicate the exact opposite.
|
I don't understand how the language comes into it. The compiler can generate whatever correct code is most efficient for the operation.
Delegates are not mutable, so I'm not sure what this is referring to. |
@gafter The language comes into it if it allows the explicit conversion You're right, when it comes to immutability, reflection is negligible. |
Although this will do the trick, I wouldn't call it idiomatic. People are used to casting, but I'd guess not many people know of this Invoke "trick". Edited to add: I found a mention to Invoke in the remarks for the Delegate class. Not what I would call discoverable... |
@gafter I was surprised to see this thread with no mention of event handlers. If two event handlers have matching (incl. variance) but different delegate types event D1 D1Event {
add { D2Event += value; } ...
} because |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Original post: #3661
.NET has inherited a whole sea of delegate types from .NET 1.0. Thanks to Func and Action they are largely obsolete now. C# should allow implicit conversions between delegate types of compatible signature.
See https://lostechies.com/jimmybogard/2008/03/26/stop-creating-custom-delegate-types/
public delegate bool CustomMatchingFunction(string value);
All of these assignments should just work. If there are objections to making this an implicit conversion an explicit one would work as well.
The text was updated successfully, but these errors were encountered: