Delegates with same signature

2019-02-22 23:42发布

问题:

My question is a bit similar to this one: How to convert an action to a defined delegate of the same signature?

Why there is no implicit convertion between delegates with same signature. For example, code:

class Program
{
    private delegate void Foo1(int x);
    private delegate void Foo2(int x);


    static void Main(string[] args)
    {
        Foo1 foo1 = Console.WriteLine;
        Foo2 foo2 = Console.WriteLine;

        Call(foo1);

        Call2(foo2);
    }

    static void Call(Action<int> action)
    {
        action(10);
    }

    static void Call2(Foo1 action)
    {
        action(10);
    }
}

it does not compile because there isn't implicit convertion from Action<int> to Foo1. But normaly it's the same thing. So it mean this names are aliases, not actualy names. So i think it was great idea to think about it like aliases. So in this case we have 3 aliases of a delegate, that get one int value and returns nothing. And this delegates are fully interchangeable one by another. But we don't have it. So question is: why? By signatures it's the same thing, and there isn't any implementation, so delegates with same signature are one and same with many aliases...

Is it C# defect or there are reasons for it? As to me, i don't see any.

回答1:

There's no implicit conversion between those two delegates for the same reason that there's no implicit conversion between these two types:

public sealed class Foo1
{
    public string Value { get; set; }
}

public sealed class Foo2
{
    public string Value { get; set; }
}

Just because two classes have the same fields doesn't mean that you should be able to treat one as if it were another. The same logic applies to delegates (which are also types, mind you).

There is semantic meaning applied to the creation of that type. If someone created a Foo1 they want it to be a Foo1, not a Foo2. If they're going out of their way to use a Foo1 where a Foo2 is expected, it's a big red flag that even though the types appear similar, there is a semantic difference between these two types. If the programmer knows something that the compiler doesn't, they can use an explicit conversion of some sort to indicate that they know what they're doing.

(The previous paragraph was intentionally written to apply equally to your delegates, and the classes I provided above.)