литейщик - PullRequest
       0

литейщик

19 голосов
/ 12 августа 2010

Я довольно новичок в 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....
    }
.....

Я не знаю, как заставить это преобразование работать, если только не использовать тот же делегат, что и у типа.Но в моем проекте было бы более красиво, если бы делегаты имели разные имена (поскольку они существуют в разных классах.

Надеюсь, вы мне поможете.

Ответы [ 2 ]

25 голосов
/ 12 августа 2010

Вы не можете напрямую конвертировать между делегатами. То, что вы можете сделать, это сделать нового делегата из существующего, совместимого. Так что если вы измените свой код на:

 delegateB myFuncDelegate = new delegateB(myTest());

это будет работать. (Обратите внимание, что «совместимость» не обязательно означает, что подписи идентичны - подробности см. В спецификации языка.)

Просто, чтобы сделать это немного понятнее для других читателей, вот простой пример, который не требует вызовов методов.

// 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);
    }
}

Обратите внимание, что есть одно исключение из этого правила "без преобразований" - общая дисперсия в C # 4. Например, в C # 4 вы можете написать:

 Action<object> foo = x => Console.WriteLine(x.GetHashCode());
 Action<string> bar = foo;

... потому что Action<T> является контравариантным в T (так что фактически оно объявлено как Action<in T>). Это ссылочное преобразование - оно не создает новый делегат, как в первом примере. Однако это не доступно только для «совместимых» делегатов - только для общих.

6 голосов
/ 05 декабря 2013

Кроме того, не совсем то, о чем вы спрашивали, но интересно - это не работает:

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

func_object = func_double;

Но это так:

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

func_object = func_string;

Разница в том, что в качестве примера строки используется ссылочные типы, которые могут приводить к объекту, в то время как двойник должен быть помещен в коробку, тем самым блокируя прямое приведение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...