Що означає синтаксис '=>' у C #?


84

Я щойно натрапив на цей синтаксис у деяких питаннях на цьому форумі, але Google та будь-який інший пошуковий механізм, як правило, блокують будь-що, крім літер та цифр, тому неможливо знайти "=>".

То хто-небудь може сказати мені, що це таке і як воно використовується?


Відповіді:


86

Це лямбда-оператор.

Від C # 3 до C # 5 це використовувалось лише для лямбда-виразів . В основному це коротша форма анонімних методів, представлених у C # 2, але їх також можна перетворити у дерева виразів .

Як приклад:

Func<Person, string> nameProjection = p => p.Name;

еквівалентно:

Func<Person, string> nameProjection = delegate (Person p) { return p.Name; };

В обох випадках ви створюєте делегата з Personпараметром, повертаючи ім'я цієї людини (у вигляді рядка).

У C # 6 той самий синтаксис використовується для членів , наповнених виразом , наприклад

// Expression-bodied property
public int IsValid => name != null && id != -1;

// Expression-bodied method
public int GetHashCode() => id.GetHashCode();

Дивитися також:

(І справді багато подібних питань - спробуйте теги лямбда та лямбда-вирази .)


1
Оскільки запитання нічого не говорить про точний випадок, про який задають, можливо, подумайте про оновлення цієї відповіді, щоб містити також новий синтаксис виразного синтаксису члена?
Лассе В. Карлсен,

1
Приємно :) Щойно прийшов сюди, оскільки це питання було використано як мішень для закриття дублікатів, тому подумав, що було б непогано мати 1 відповідь, а не йти на полювання на іншу в тих інших випадках :)
Лассе В. Карлсен,

15

Це набагато коротша форма позначення методу. Наступні приблизно еквівалентні:

// explicit method
int MyFunc(int pParam) {
   return pParam;
}

// anonymous (name-less) method
// note that the method is "wrapped" up in a hidden object (Delegate) this way
// so there is a very tiny bit of overhead compared to an explicit method
// (though it's really the assignment that causes that and would also happen
// if you assigned an explicit method to a reference)
Func<int, int> MyFunc = delegate (int pParam) { return pParam; };

// lambda expression (also anonymous)
// basically identical to anonymous method,
// except with everything inferred as much as possible, intended to be minimally verbose
Func<int, int> MyFunc = x => x;

// and => is now also used for "expression-bodied" methods
// which let you omit the return keyword and braces if you can evaluate
// to something in one line
int MyFunc(int pParam) =>
   pParam;

Подумайте про лямбда-вираз, як про те, що він сказав: "щось дано, щось повернути". У наведеному вище прикладі лямбда-вираз x => xговорить "задано х, повернути х", хоча лямбда-вирази не обов'язково повинні щось повертати, і в цьому випадку ви можете прочитати їх як "дано х, зробіть щось із х".

Також зверніть увагу, що є три речі, які називаються "делегат", і які спочатку можуть дуже заплутати.

Анонімний метод використовує delegateключове слово, але визначає метод без імені:

Func<int, int> = delegate (int x) { return x; };

Присвоєння методу (анонімного, явного або лямбда-посилання) посилання викликає створення прихованого Delegateобгорткового об'єкта, що дозволяє посилатися на метод. (В основному це свого роду "вказівник керованої функції".)

А потім ви також можете оголосити підписи іменованих методів, використовуючи також delegateключове слово:

public delegate int TestFunc(int x, int y);

TestFunc myFunc = delegate (int x, int y) { return x + y; };

Це оголошує іменований підпис, TestFuncякий займає два ints і повертає int, а потім оголошує посилання делегата того типу, якому потім призначається анонімний метод із відповідним підписом.


14

Це означає дивовижність. Наприклад,

x => x + 1

представляє метод, який приймає x як параметр і повертає його наступника.

button.Click += new EventHandler((sender, e) => methodInfo.Invoke(null, new object[] { sender, e }));

присвоює кнопці обробник події, викликаючи метод, який містить MethodInfo.


10

ось простий приклад з msdn

delegate int del(int i);
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25

Будь-що перед => є вхідними параметрами, а будь-що після - виразом. Ви можете мати кілька вхідних параметрів. Лямбди в основному використовуються з Linq.


8

Замість використання анонімного методу, подібного до цього:

somevar.Find(delegate(int n)
{
   if(n < 10)
      return n;
});

ви просто пишете це так:

somevar.Find(n => n < 10);

Він буде приймати тип даних на основі поверненого значення.


3

=> Маркер підтримується в двох формах: у якості оператора лямбда і в якості роздільника імені членів і здійснення членів у визначенні вираження тіла.

Лямбда-оператор

У лямбда-виразах оператор лямбда => відокремлює вхідні змінні ліворуч від тіла лямбда праворуч.

У наступному прикладі використовується функція LINQ із синтаксисом методу, щоб продемонструвати використання лямбда-виразів:

string[] words = { "bot", "apple", "apricot" };
int minimalLength = words
  .Where(w => w.StartsWith("a"))
  .Min(w => w.Length);
Console.WriteLine(minimalLength);   // output: 5

Визначення тіла виразу

Визначення тіла виразу має такий загальний синтаксис:

member => expression;

де вираз - дійсний вираз. Зверніть увагу, що вираз може бути виразом оператора, лише якщо тип повернення елемента недійсний, або якщо член є конструктором, фіналізатором або засобом доступу до набору властивостей.

У наступному прикладі показано визначення тіла виразу для методу Person.ToString:

public override string ToString() => $"{fname} {lname}".Trim();

Це скорочена версія наступного визначення методу:

public override string ToString()
{
   return $"{fname} {lname}".Trim();
}

4
Якщо ви збираєтеся копіювати та вставляти відповіді з інших веб-сайтів, принаймні додайте посилання на джерело .
Кнеліс

1

Це в основному означає "входить", як параметр

MyObjectReference => MyObjectReference.DoSomething()

Зазвичай ви використовуєте їх для передачі функцій у методи як параметри або в оператори LINQ

MyCollection.Where(myobj => myobj.Age>10)

Наприклад.


0

Це частина синтаксису лямбда-виразу. Лямбда-вираз є по суті скороченою формою делегата або анонімного методу. Для ілюстрації припустимо, що у мене є масив рядків, що відповідають літерам алфавіту. Я міг виділити члени цього масиву, що містив значення, більші за "E", з таким виразом LINQ:

var someLetters = alphabet.Where (l => l> "E");

Частина лямбда-виразу ліворуч від "=>" визначає ім'я змінної для тесту (яке встановлено для окремих членів алфавіту), а частина лямбда-виразу праворуч від "=>" визначає обробці. У цьому випадку обробка видає булеве значення, яке логіка Where використовує для визначення того, чи передається кожен член алфавіту до масиву someLetters.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.