Как преобразовать действие в определенный делегат с той же подписью? - PullRequest
6 голосов
/ 20 октября 2011
class Test
{
    public delegate void FruitDelegate(Fruit f);

    public void Notify<T>(Action<T> del) where T : Fruit
    {
        FruitDelegate f = del; // Cannot implicitly convert type 'Action<T>' to 'FruitDelegate
    }
}

Fruit - пустой класс.Оба этих делегата имеют одинаковую подпись.

Кажется, я не могу заставить это работать.Возможно, это помогло бы, если бы я объяснил, что я пытаюсь сделать (предоставив некоторый контекст).

Я хочу создать класс, имеющий общий статический метод, который предоставляет тип и обратный вызов метода (как в приведенном выше примере).

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

public void SomeMethod()
{
    Test.Notify<Apple>(AppleHandler);
}

private void AppleHandler(Apple apple)
{

}

Вместо этого:

public void SomeMethod()
{
    Test.Notify<Apple>(AppleHandler);
}

private void AppleHandler(Fruit fruit)
{
    Apple apple = (Apple)fruit;
}

Возможно ли такое?Работали над этим несколько часов без особой удачи = /

Ответы [ 3 ]

7 голосов
/ 20 октября 2011

это то, что вы хотите?

static void Main(string[] args)
{

    Program p = new Program();
    p.SomeMethod();
}

public class Fruit
{ }

public class Apple : Fruit { }

public delegate void FruitDelegate<in T>(T f) where T : Fruit;

class Test
{
    public static void Notify<T>(FruitDelegate<T> del)
        where T : Fruit, new()
    {
        T t = new T();
        del.DynamicInvoke(t);
    }
}

private void AppleHandler(Apple apple)
{
    Console.WriteLine(apple.GetType().FullName);
}

public void SomeMethod()
{
    FruitDelegate<Apple> del = new FruitDelegate<Apple>(AppleHandler);
    Test.Notify<Apple>(del);
}
2 голосов
/ 20 октября 2011

Есть веская причина, по которой вы не можете этого сделать.Предположим, что остальная часть вашего метода была:

class Test
{
    public delegate void FruitDelegate(Fruit f);

    public void Notify<T>(Action<T> del) where T : Fruit
    {
        FruitDelegate f = del; 
        f(new Banana());  //should be legal, but del may be Action<Apple>
    }
}

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

1 голос
/ 20 октября 2011

Как насчет этого?

public void Notify<T>(Action<T> del) where T : Fruit
{
    FruitDelegate f = fruit => del((T)fruit);
}

Экземпляр FruitDelegate при вызове генерирует исключение InvalidCastException, если, скажем, AppleHandler был вызван с аргументом Banana.

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