Подтвердить что ты не робот

С# - невозможно объявить делегата в рамках метода

Я действительно скрываюсь здесь.

Мне интересно почему. Я не могу объявить тип делегата в методе, но я должен сделать это на уровне класса.

namespace delegate_learning
{
    class Program
    {
        // Works fine
        public delegate void anon_delgate(int i);

        static void Main(string[] args)
        {
            HaveFun();
            Console.Read();
        }

        public static void HaveFun()
        {
            // Throws an error :/
            //delegate void anon_delgate(int i);

            anon_delgate ad = delegate(int i) { Console.WriteLine(i.ToString());};
        }


    }
}

Изменить: Я изучаю лямбда-выражения и подкрепляюсь тем, как это было до Лямбдаса, для моих личных знаний.

4b9b3361

Ответ 1

// Throws an error :/
delegate void anon_delgate(int i);

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

namespace A
{
   delegate void X(int i); //allowed
   public class B
   {
         delegate void Y(int i); //also allowed
   }
}

Кстати, почему бы вам не написать это:

anon_delgate ad = i => Console.WriteLine(i.ToString());

Это выражение называется лямбда-выражением.

Ответ 2

Вы не можете объявить какой-либо тип внутри метода. Поэтому давайте рассмотрим вопрос "почему я не могу объявить тип внутри метода в С#?"

Ответ на вопросы этой формы всегда один и тот же. Для того, чтобы вы могли что-то сделать на С#, должно произойти следующее:

  • Кто-то должен подумать об этой функции
  • Кто-то должен разработать функцию
  • Кто-то должен написать спецификацию функции
  • Кто-то должен реализовать эту спецификацию
  • Кто-то должен протестировать реализацию
  • Кто-то должен документировать эту функцию (и переводить документацию на десяток разных языков.)
  • Как-то код реализации должен попасть в "транспортное средство", с помощью которого он может быть отправлен клиентам.

До сих пор из всего, что было в этом списке, произошло только первое. Остальные из них никогда не случались, поэтому вы не можете использовать эту функцию в С#.

Похоже, вы подразумеваете, что состояние функции по умолчанию "реализовано" и что мы должны придумать по какой-то причине сделать его не реализованным. Уверяю вас, что это не так; состояние всех возможных функций по умолчанию "не реализовано", и у нас должно быть оправдание тратить время, деньги и усилия, необходимые для реализации функции. Пока никто не сделал убедительного случая, что объявления локального типа стоят; если вы хотите попытаться сделать убедительный случай, я бы хотел его услышать.

Ответ 3

Объявление делегата внутри метода будет похоже на объявление класса внутри метода, потому что компилятор переписывает объявление делегата в объявление класса.

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

Ответ 4

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

С или без лямбда вы можете просто заменить anon_delgate ad на Action<int>. Поскольку никто из внешних методов не может видеть anon_delegate, его существование не добавляет исключительной ценности. Вы хотите определить тип делегата локально, но вы можете кодировать любую информацию о цели делегата внутри имени переменной, а не в типе переменной. Десятки уже определенных делегатов * Action и Func делают очень редким, что вы не сможете найти делегат, который соответствует вашим потребностям.

Вкратце, я вижу эту функцию как добавление каких-то больших затрат на Эрика, но не вижу в ней достаточных преимуществ, чтобы компенсировать эти затраты, не смещая дополнительная путаница, возникающая в результате предоставления другой функции, которая может запутать разработчиков.

Эта функция не добавляет каких-либо выразительных возможностей для языка, ее небытие легко обрабатывается, и я думаю, что это потеряло бы больше времени для разработчиков (сделав С# более трудным для изучения/использования), чем это сэкономит.

* (ну, меньше их в более старых версиях С#, но спрашивать, почему функция не находится в более старой версии С#, когда она может быть полезна, довольно неинтересна, когда ответ "вау, это полезно. Мы добавили его в следующую версию." )

Ответ 5

Почему бы вам просто не использовать лямбда-выражения?

Action<int> ad = i => Console.WriteLine(i.ToString());

Ответ 6

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

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