铸造代表

Jak*_*obJ 23 c#

我对c#很陌生,所以我的问题可能很简单,但是这里有.

我一直在尝试与代表合作,并且有点坚持这个问题.

.....
    public delegate double delegateA();
    public delegate double delegateB();

    public static double myFunc()
    {
        return 0;
    }
    public static delegateA myTest()
    {
        return myFunc;
    }

    static void Main(string[] args)
    {
        delegateB myFuncDelegate;

        myFuncDelegate = myTest();  // <-- Error: Cannot implicitly convert type....
    }
.....
Run Code Online (Sandbox Code Playgroud)

我不知道如何使这个转换工作,除非使用相同的委托作为类型.但是在我的项目中,代表的名称会更加漂亮(因为它们存在于不同的类中).

希望您能够帮助我.

Jon*_*eet 29

你不能直接在这样的代表之间进行转换.你可以做的是从一个现有的,兼容的代表创建一个代表.因此,如果您将代码更改为:

 delegateB myFuncDelegate = new delegateB(myTest());
Run Code Online (Sandbox Code Playgroud)

那可行.(请注意,"兼容性"并不一定意味着签名相同 - 有关详细信息,请参阅语言规范.)

只是为了让其他读者稍微清楚一点,这里有一个更简单的完整示例,它不需要任何方法调用.

// Two delegate types with the same signature
delegate void Foo();
delegate void Bar();

class Test
{
    static void Main()
    {
        // Actual value is irrelevant here
        Foo foo = null;

        // Error: can't convert like this
        // Bar bar = foo;

        // This works fine
        Bar bar = new Bar(foo);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,此"无转换"规则有一个例外 - C#4中的泛型差异.例如,在C#4中,您可以编写:

 Action<object> foo = x => Console.WriteLine(x.GetHashCode());
 Action<string> bar = foo;
Run Code Online (Sandbox Code Playgroud)

...因为它Action<T>逆变T(因此它实际上被声明为Action<in T>).这是一个引用转换 - 它不会像第一个示例那样创建新的委托.但是,这不仅仅适用于"兼容"代表 - 只有通用代理.

  • 请注意,这将产生一个委托,其目标是第一个委托的Invoke方法,您可能不需要这种间接级别。有关如何获取直接引用原始目标的新委托的信息,请参见http://stackoverflow.com/a/9290684/497397及其周围的讨论。 (3认同)

Mal*_*chi 6

此外,不完全是你问的问题,但有趣的是 - 这不起作用:

Func<double> func_double = () => 1;
Func<object> func_object;

func_object = func_double;
Run Code Online (Sandbox Code Playgroud)

但这样做:

Func<string> func_string = () => "hello";
Func<object> func_object;

func_object = func_string;
Run Code Online (Sandbox Code Playgroud)

作为字符串示例的差异是使用可以强制转换为对象的引用类型,而必须将double加框,从而阻止直接强制转换