-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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: Support delegate signature equivalence #4331
Comments
I think this is definitely worth doing. The purpose of verification is to prove that type safety will not be violated. If you can prove that all types involved in the delegate are equivalent, then type safety will not be violated, so there's no reason to report it as problematic. |
To note, this is not without type-safety issues. While the CLR will happily invoke the delegate it is not recognized as that type. For example: public static boolean Test(Predicate<string> predicate) {
object obj = predicate;
boolean isPredicate = (obj is Predicate<string>); // false!
predicate = (Predicate<string>) obj; // InvalidCastException!
return predicate("Foo!");
}
Func<string, bool> predicate = () => true;
Test(predicate); // assuming compiler allowed this and running full-trust Understandably that might make this problematic, but I'd love to at least use this proposal as a starting point to perhaps discuss delegate signature equivalence either through the CLR directly or perhaps with efficient conversion methods in the BCL. |
@HaloFour Interesting point, but I have to wonder how relevant it is. I don't believe I've ever seen code that takes a variable of formal type |
There is one more small problem - current implementation of Delegate.Combine will throw an exception if delegates of different types passed to it, even if their types are compatible. |
@iskiselev This appears to be based on a runtime-level (C++) method called That actually brings up an interesting idea: it implies that this whole thing could be implemented fairly simply by defining ...maybe. Probably not the compiler, because the Good catch! :) |
Do we have some progress on this feature? if (obj is Action){ ... }
else if (obj is Task) { .... } if inside the Approaches:
// The same annotation technique as for "Nullable" or "Dynamic" for generics support.
public class SupportEquivalenceAttribute: Attribute
{
}
// C# syntax
public void MyNewMethod(var Action a)
{
....
}
// IL representation:
public void MyNewMethod([SupportEquivalence]Action a)
{
if (a.Type.Name == "Action") // Compiler warning or error, because "a" could contain a different type of delegate
{
}
if (Delegate.IsEquivalent<Action>(a)) // Correct implementation
{
}
}
public void MyOldMethod(Action a)
{
}
delegate void MyAction();
public void MyCode()
{
MyAction action = ()=>Console.WriteLine("HelloWorld");
MyOldMethod(action); // Compiler Error!
MyNewMethod(action) // Works, as implementation of MyNewMethod declares that it's support "Delegate equivalence feature".
} |
Due to lack of recent activity, this issue has been marked as a candidate for backlog cleanup. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process. This process is part of our issue cleanup automation. |
This issue will now be closed since it had been marked |
See Roslyn: Convert delegate types with compatible signature automatically
Currently the various CLR compilers do not permit treating one delegate of a specific signature as the same as another delegate of an identical signature. The compilers that do (VB.NET) do so by wrapping the existing delegate instance with the new delegate which incurs a performance penalty at the time of invocation.
It appears that for whatever reason, accidentally or otherwise, the CLR/JIT have no real issue using one delegate in place of another. The verifier does complain that an unexpected type is on the stack for the specified call but otherwise the program does execute.
I propose that the verifier be modified that if the type expected and the type on the stack are different but are both delegate types, and that the
Invoke
method on both delegates share the same signature that the verifier allow the operation.This would permit delegates of identical signatures to be considered equivalent without the performance penalty either at the time of conversion or the time of invocation.
The text was updated successfully, but these errors were encountered: