Как я могу написать общий анонимный метод?

В частности, я хочу написать это:

public Func<IList<T>, T> SelectElement = list => list.First();

Но я получаю синтаксическую ошибку в T. Разве у меня нет общего анонимного метода?


person mpen    schedule 02.12.2010    source источник
comment
решено! stackoverflow.com/questions/4338867   -  person mpen    schedule 02.12.2010


Ответы (4)


Нет извини. Для этого потребуются общие поля или общие свойства, которые не являются функциями, поддерживаемыми C#. Лучшее, что вы можете сделать, это создать общий метод, который вводит T:

public Func<IList<T>, T> SelectionMethod<T>() { return list => list.First(); }

И теперь вы можете сказать:

Func<IList<int>, int> selectInts = SelectionMethod<int>();
person Eric Lippert    schedule 02.12.2010

Конечно можно, но T надо знать:

class Foo<T>
{
    public Func<IList<T>, T> SelectionMethod = list => list.First();
}

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

public Func<IList<T>, T> SelectionMethod<T>()
{
    return list => list.First();
}

Но все же кому-то во время компиляции нужно будет знать это T.

person Darin Dimitrov    schedule 02.12.2010
comment
Да.. в этом проблема. Я не знаю, что такое Т. Это может быть символ или строка. - person mpen; 02.12.2010
comment
Что ж, будем надеяться, что потребитель (тот, кто его создает) класса Foo<T> узнает об этом. Если вы никогда не знаете этого во время компиляции, то дженерики вам не подходят. - person Darin Dimitrov; 02.12.2010
comment
Что ж, тогда ваш метод или ваш класс должны принимать общий параметр T. - person cdhowie; 02.12.2010
comment
Другая проблема заключается в том, что я хочу, чтобы пользователь мог переопределить метод выбора, поэтому я использовал его как анонимную функцию :) Я знаю, что такое T, когда я вызываю этот метод, но я использую его в 2 разных местах ( один раз в List‹char›, один раз в List‹string›), и я хочу использовать один и тот же метод для обоих. - person mpen; 02.12.2010
comment
Что ж, тогда вы можете превратить это поле SelectionMethod в виртуальный универсальный метод, чтобы пользователь мог его переопределить. Здесь действительно вопрос метода и поля. Методы могут быть универсальными, поля — нет. Так говорит спецификация. Это так просто. Вы не можете бороться против спецификации или системы типов. - person Darin Dimitrov; 02.12.2010
comment
Под переопределением я имел в виду не подкласс, а изменение свойства. - person mpen; 02.12.2010
comment
Итак, если пользователь должен изменить это поле (не свойство), почему бы вам не предоставить ему общий метод, который будет принимать делегата: public void DoSomething<T>(Func<IList<T>, T> foo) { ... }. Теперь, когда пользователь вызывает этот метод, он может передать в качестве аргумента любое выражение, которое ему нравится: DoSomething(x => x.First()); и внутри метода вы будете выполнять эту работу. Вы могли бы даже предоставить перегрузку этого метода, которая будет делать .First() вещи: public void DoSomething<T>() { ... } и внутри вы создадите анонимный делегат. - person Darin Dimitrov; 02.12.2010
comment
@Darin: я хотел указать это на уровне класса для повторного использования ... но пока это самое близкое решение. Может надо так сделать. - person mpen; 02.12.2010
comment
@Darin: На самом деле, это тоже не сработает ... потому что, как я уже сказал, T принимает два разных значения внутри функции. - person mpen; 02.12.2010

Вы объявили только возвращаемый тип как общий.

Попробуй это:

public Func<IList<T>, T> SelectionMethod<T>() { return list => list.First(); }

Имя объекта, который вы объявляете, должен включать параметры типа, чтобы он был универсальным. Компилятор поддерживает только универсальные классы и универсальные методы.

Итак, для универсального класса вы должны иметь

class MyGeneric<T> { 
   // You can use T here now
   public T MyField;
 }

Или, для методов

public T MyGenericMethod<T>( /* Parameters */ ) { return T; }

Вы можете использовать T в качестве возвращаемого параметра, только если он был объявлен в имени метода первым.

Несмотря на то, что похоже, что возвращаемый тип объявлен перед фактическим методом, компилятор не читает его таким образом.

person Matt Brunell    schedule 02.12.2010
comment
А? Нет, не делал..даже до редактирования. И какое это имеет отношение к чему-либо? - person mpen; 02.12.2010
comment
Это лучшее объяснение. Однако я хотел общую лямбду, которой, я думаю, не существует. - person mpen; 02.12.2010

person    schedule
comment
Добро пожаловать в СО. При ответе на вопрос предоставьте объяснение, связанное с вашим кодом. Некоторые люди могут не понять ваш код или не увидеть, как он отвечает на вопрос. См. как написать хороший ответ - person Nuageux; 02.06.2017