Поиск…


Вступление

В C # оператор - это программный элемент, который применяется к одному или нескольким операндам в выражении или инструкции. Операторы, которые принимают один операнд, такой как оператор приращения (++) или новый, называются унарными операторами. Операторы, которые принимают два операнда, такие как арифметические операторы (+, -, *, /), называются двоичными операторами. Один оператор, условный оператор (? :), принимает три операнда и является единственным тернарным оператором в C #.

Синтаксис

  • публичный статический оператор OperandType оператораSymbol (операнд операнда1)
  • публичный статический оператор OperandType оператораSymbol (OperandType operand1, OperandType2 operand2)

параметры

параметр подробности
operatorSymbol Перегруженный оператор, например +, -, /, *
OperandType Тип, который будет возвращен перегруженным оператором.
operand1 Первый операнд, который будет использоваться при выполнении операции.
operand2 Второй операнд, который будет использоваться при выполнении операции, при выполнении двоичных операций.
заявления Необязательный код, необходимый для выполнения операции перед возвратом результата.

замечания

Все операторы определяются как static methods и они не являются virtual и они не наследуются.

Приоритет оператора

Все операторы имеют особый «приоритет» в зависимости от того, к какой группе относится оператор (операторы той же группы имеют одинаковый приоритет). Значение некоторых операторов будет применено к другим. Ниже следует список групп (содержащих их соответствующие операторы), упорядоченные по приоритету (сначала по высоте):

  • Первичные операторы

    • ab - доступ к члену.
    • a?.b - Нулевой доступ к условному члену.
    • -> - разыменование указателя в сочетании с доступом участника.
    • f(x) - вызов функции.
    • a[x] - индекс.
    • a?[x] - Нулевой условный индекс.
    • x++ - Постерическое приращение.
    • x-- - Постфиксный декремент.
    • new - Создание экземпляра.
    • default(T) - Возвращает инициализированное значение по умолчанию типа T
    • typeof - Возвращает объект Type операнда.
    • checked - Включает проверку числового переполнения.
    • unchecked - отключает проверку числового переполнения.
    • delegate - объявляет и возвращает экземпляр делегата.
    • sizeof - Возвращает размер в байтах операнда типа.
  • Унарные операторы

    • +x - Возвращает x .
    • -x - Числовое отрицание.
    • !x - Логическое отрицание.
    • ~x - Побитовое дополнение / объявляет деструкторы.
    • ++x - Приращение префикса.
    • --x - --x префиксов.
    • (T)x - Тип литья.
    • await - await выполнения Task .
    • &x - возвращает адрес (указатель) x .
    • *x - разыменование указателя.
  • Мультипликативные операторы

    • x * y - Умножение.
    • x / y - Отдел.
    • x % y - модуль.
  • Аддитивные операторы

    • x + y - Дополнение.
    • x – y - вычитание.
  • Побитовые операторы сдвига

    • x << y - сдвинуть бит влево.
    • x >> y - сдвинуть бит вправо.
  • Операторы реляционного / типа тестирования

    • x < y - Меньше чем.
    • x > y - больше.
    • x <= y - меньше или равно.
    • x >= y - больше или равно.
    • is - совместимость Тип.
    • as - Преобразование типа.
  • Операторы равенства

    • x == y - Равенство.
    • x != y - Не равно.
  • Логический И Оператор

    • x & y - Логическое / побитовое И.
  • Логический оператор XOR

    • x ^ y - Логический / побитовый XOR.
  • Логический оператор ИЛИ

    • x | y - логическое / побитовое ИЛИ.
  • Условный И Оператор

    • x && y - Короткое замыкание логического И.
  • Условный ИЛИ Оператор

    • x || y - Короткое замыкание логического ИЛИ.
  • Оператор Null-coalescing

    • x ?? y - возвращает x если он не равен нулю; в противном случае возвращает y .
  • Условный оператор

    • x ? y : z - вычисляет / возвращает y если x истинно; в противном случае - z .

Связанный контент

Перегружаемые операторы

C # позволяет пользовательским типам перегружать операторы путем определения статических функций-членов с использованием ключевого слова operator .
Следующий пример иллюстрирует реализацию оператора + .

Если у нас есть класс Complex представляющий комплексное число:

public struct Complex
{
    public double Real { get; set; }
    public double Imaginary { get; set; }
}

И мы хотим добавить опцию для использования оператора + для этого класса. то есть:

Complex a = new Complex() { Real = 1, Imaginary = 2 };
Complex b = new Complex() { Real = 4, Imaginary = 8 };
Complex c = a + b;

Нам нужно будет перегрузить оператор + для класса. Это делается с использованием статической функции и ключевого слова operator :

public static Complex operator +(Complex c1, Complex c2)
{
   return new Complex 
   { 
       Real = c1.Real + c2.Real,
       Imaginary = c1.Imaginary + c2.Imaginary 
   };
}

Операторы, такие как + , - , * , / могут быть перегружены. Сюда также входят операторы, которые не возвращают один и тот же тип (например, == и != Могут быть перегружены, несмотря на возврат булевых элементов). Здесь также применяется правило, относящееся к парам.

Операторы сравнения должны быть перегружены парами (например, если < перегружен, > также необходимо перегрузить).

Полный список перегружаемых операторов (а также неперегружаемых операторов и ограничений, помещенных на некоторые перегружаемые операторы) можно увидеть в MSDN - Overloadable Operators (Руководство по программированию на C #) .

7,0

перегрузка operator is была введена с помощью механизма сопоставления шаблонов C # 7.0. Для получения дополнительной информации см Pattern Matching

Учитывая тип Cartesian определенный следующим образом

public class Cartesian
{
    public int X { get; }
    public int Y { get; }
}   

Перегружаемый operator is может быть определен, например, для Polar координат

public static class Polar
{
    public static bool operator is(Cartesian c, out double R, out double Theta)
    {
        R = Math.Sqrt(c.X*c.X + c.Y*c.Y);
        Theta = Math.Atan2(c.Y, c.X);
        return c.X != 0 || c.Y != 0;
    }
}

который можно использовать следующим образом

var c = Cartesian(3, 4);
if (c is Polar(var R, *))
{
    Console.WriteLine(R);
}

(Пример взята из сопоставимой документации по шаблону Roslyn )

Реляционные операторы

Равно

Проверяет, равны ли поставленные операнды (аргументы)

"a" == "b"     // Returns false.
"a" == "a"     // Returns true.
1 == 0         // Returns false.
1 == 1         // Returns true.
false == true  // Returns false.
false == false // Returns true.

В отличие от Java, оператор сравнения равенства работает со строками.

Оператор сравнения равенства будет работать с операндами разных типов, если неявный листинг существует от одного к другому. Если подходящий неявный бросок не существует, вы можете вызвать явное приведение или использовать метод для преобразования в совместимый тип.

1 == 1.0              // Returns true because there is an implicit cast from int to double.
new Object() == 1.0   // Will not compile.
MyStruct.AsInt() == 1 // Calls AsInt() on MyStruct and compares the resulting int with 1.

В отличие от Visual Basic.NET оператор сравнения равенства не совпадает с оператором присваивания равенства.

var x = new Object();
var y = new Object();
x == y // Returns false, the operands (objects in this case) have different references.
x == x // Returns true, both operands have the same reference.

Не путать с оператором присваивания ( = ).

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

Неравномерно

Проверяет, не равны ли поставленные операнды.

"a" != "b"     // Returns true.
"a" != "a"     // Returns false.
1 != 0         // Returns true.
1 != 1         // Returns false.
false != true  // Returns true.
false != false // Returns false.

var x = new Object();
var y = new Object();
x != y // Returns true, the operands have different references.
x != x // Returns false, both operands have the same reference.

Этот оператор фактически возвращает обратный результат к результату оператора equals ( == )

Лучше чем

Проверяет, превышает ли первый операнд второй операнд.

3 > 5    //Returns false.
1 > 0    //Returns true.
2 > 2    //Return false.

var x = 10;
var y = 15;
x > y    //Returns false.
y > x    //Returns true.

Меньше, чем

Проверяет, является ли первый операнд меньше второго операнда.

2 < 4     //Returns true.
1 < -3    //Returns false.
2 < 2     //Return false.

var x = 12;
var y = 22;
x < y    //Returns true.
y < x    //Returns false.

Больше, чем равно

Проверяет, является ли первый операнд больше, чем второй операнд.

7 >= 8    //Returns false.
0 >= 0    //Returns true.

Меньше, чем равно

Проверяет, является ли первый операнд меньше, чем второй операнд.

2 <= 4    //Returns true.
1 <= -3    //Returns false.
1 <= 1     //Returns true. 

Операторы короткого замыкания

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

Это означает, что, если вы используете && operator как firstCondition && secondCondition, он будет оценивать secondCondition только в том случае, когда firstCondition является истинным, а fromcource - общий результат будет истинным, только если оба firstOperand и secondOperand оценены как true. Это полезно во многих сценариях, например, представьте, что вы хотите проверить, в то время как ваш список содержит более трех элементов, но вы также должны проверить, был ли список инициализирован, чтобы не запускаться в исключение NullReferenceException . Вы можете достичь этого, как показано ниже:

bool hasMoreThanThreeElements = myList != null && mList.Count > 3;

mList.Count> 3 не будет проверяться до тех пор, пока myList! = null не будет выполнен.

Логические И

&& является короткозамкнутым аналогом стандартного логического оператора AND ( & ).

var x = true;
var y = false;

x && x // Returns true.
x && y // Returns false (y is evaluated).
y && x // Returns false (x is not evaluated).
y && y // Returns false (right y is not evaluated).

Логический ИЛИ

|| является короткозамкнутым аналогом стандартного булева оператора OR ( | ).

var x = true;
var y = false;

x || x // Returns true (right x is not evaluated).
x || y // Returns true (y is not evaluated).
y || x // Returns true (x and y are evaluated).
y || y // Returns false (y and y are evaluated).

Пример использования

if(object != null && object.Property)
// object.Property is never accessed if object is null, because of the short circuit.
    Action1();
else
    Action2();

размер

Возвращает int содержащий размер типа * в байтах.

sizeof(bool)    // Returns 1.
sizeof(byte)    // Returns 1.
sizeof(sbyte)   // Returns 1.
sizeof(char)    // Returns 2.
sizeof(short)   // Returns 2.
sizeof(ushort)  // Returns 2.
sizeof(int)     // Returns 4.
sizeof(uint)    // Returns 4.
sizeof(float)   // Returns 4.
sizeof(long)    // Returns 8.
sizeof(ulong)   // Returns 8.
sizeof(double)  // Returns 8.
sizeof(decimal) // Returns 16.

* Поддерживает только определенные примитивные типы в безопасном контексте.

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

public struct CustomType
{
    public int value;
}

static void Main()
{
    unsafe
    {
        Console.WriteLine(sizeof(CustomType)); // outputs: 4
    }
}

Перегрузка операторов равенства

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

  1. object.Equals и object.GetHashCode
  2. IEquatable<T>.Equals (необязательно, позволяет избежать бокса)
  3. operator == и operator != (необязательно, позволяет использовать операторы)

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

Когда НЕ переопределенный метод Equals и оператор == работают по-разному для классов и структур. Для классов сравниваются только ссылки, а для структур значения свойств сравниваются посредством отражения, что может отрицательно повлиять на производительность. == не может использоваться для сравнения структур, если он не переопределен.

Как правило, операция равенства должна подчиняться следующим правилам:

  • Не нужно бросать исключения .
  • Рефлексивность: A всегда равна A (может быть неверна для значений NULL в некоторых системах).
  • Транзитивность: если A равно B , а B равно C , то A равно C
  • Если A равно B , то A и B имеют одинаковые хэш-коды.
  • Независимость дерева наследования: если B и C являются экземплярами Class2 унаследованными от Class1 : Class1.Equals(A,B) всегда должны возвращать то же значение, что и вызов Class2.Equals(A,B) .
class Student : IEquatable<Student>
{
    public string Name { get; set; } = "";

    public bool Equals(Student other)
    {
        if (ReferenceEquals(other, null)) return false;
        if (ReferenceEquals(other, this)) return true;
        return string.Equals(Name, other.Name);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;

        return Equals(obj as Student);
    }

    public override int GetHashCode()
    {
        return Name?.GetHashCode() ?? 0;
    }

    public static bool operator ==(Student left, Student right)
    {
        return Equals(left, right);
    }

    public static bool operator !=(Student left, Student right)
    {
        return !Equals(left, right);
    }
}

Операторы класса: членский доступ

var now = DateTime.UtcNow;
//accesses member of a class.  In this case the UtcNow property.

Операторы класса: Null Conditional Member Access

var zipcode = myEmployee?.Address?.ZipCode;
//returns null if the left operand is null.  
//the above is the equivalent of:
var zipcode = (string)null;
if (myEmployee != null && myEmployee.Address != null)
    zipcode = myEmployee.Address.ZipCode;

Операторы класса: вызов функции

var age = GetAge(dateOfBirth);
//the above calls the function GetAge passing parameter dateOfBirth.

Операторы класса: индексирование агрегированных объектов

var letters = "letters".ToCharArray();
char letter = letters[1];
Console.WriteLine("Second Letter is {0}",letter);
//in the above example we take the second character from the array
//by calling letters[1]
//NB: Array Indexing starts at 0; i.e. the first letter would be given by letters[0].

Операторы класса: нулевая условная индексация

var letters = null;
char? letter = letters?[1];
Console.WriteLine("Second Letter is {0}",letter);
//in the above example  rather than throwing an error because letters is null
//letter is assigned the value null

«Эксклюзив» или «Оператор»

Оператор для «исключительного» или «(для короткого XOR): ^

Этот оператор возвращает true, когда один, но только один, из предоставленных bools являются истинными.

true ^ false   // Returns true
false ^ true   // Returns true
false ^ false  // Returns false
true ^ true    // Returns false

Операторы битового сдвига

Операторы сдвига позволяют программистам настраивать целое число, сдвигая все его биты влево или вправо. Следующая диаграмма показывает влияние сдвига значения слева на одну цифру.

Сдвиг влево

uint value = 15;              // 00001111
 
uint doubled = value << 1;    // Result = 00011110 = 30
uint shiftFour = value << 4;  // Result = 11110000 = 240

Правый-Shift

uint value = 240;             // 11110000
 
uint halved = value >> 1;     // Result = 01111000 = 120
uint shiftFour = value >> 4;  // Result = 00001111 = 15

Неявные трансляции и явные операторы

C # позволяет пользовательским типам управлять назначением и кастом посредством использования explicit и implicit ключевых слов. Подпись метода принимает вид:

public static <implicit/explicit> operator <ResultingType>(<SourceType> myType)

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

Пример как implicit и explicit приведения в действие:

public class BinaryImage 
{
    private bool[] _pixels;

    public static implicit operator ColorImage(BinaryImage im)
    {
        return new ColorImage(im);
    }

    public static explicit operator bool[](BinaryImage im)
    {
        return im._pixels;
    }
}

Разрешить следующий синтаксис:

var binaryImage = new BinaryImage();
ColorImage colorImage = binaryImage; // implicit cast, note the lack of type 
bool[] pixels = (bool[])binaryImage; // explicit cast, defining the type

Операторы литья могут работать в обоих направлениях, переходя от вашего типа и переходя к вашему типу:

public class BinaryImage
{
    public static explicit operator ColorImage(BinaryImage im)
    {
        return new ColorImage(im);
    }

    public static explicit operator BinaryImage(ColorImage cm)
    {
        return new BinaryImage(cm);
    }
}

И, наконец, в as ключевых слов, которые могут быть вовлечены в литейном в иерархии типов, не действуют в этой ситуации. Даже после определения explicit или implicit броска вы не можете:

ColorImage cm = myBinaryImage as ColorImage;

Он будет генерировать ошибку компиляции.

Бинарные операторы с присвоением

C # имеет несколько операторов, которые могут быть объединены с знаком = чтобы оценить результат оператора, а затем назначить результат исходной переменной.

Пример:

x += y

такой же как

x = x + y

Операторы присваивания:

  • +=
  • -=
  • *=
  • /=
  • %=
  • &=
  • |=
  • ^=
  • <<=
  • >>=

? : Тернарный оператор

Возвращает одно из двух значений в зависимости от значения булевого выражения.

Синтаксис:

condition ? expression_if_true : expression_if_false;

Пример:

string name = "Frank";
Console.WriteLine(name == "Frank" ? "The name is Frank" : "The name is not Frank");

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

В этом примере сложная тройная операция оценивает функцию clamp и возвращает текущее значение, если оно находится в пределах диапазона, min значение, если оно находится ниже диапазона, или max значение, если оно находится выше диапазона.

light.intensity = Clamp(light.intensity, minLight, maxLight);

public static float Clamp(float val, float min, float max)
{
    return (val < min) ? min : (val > max) ? max : val;
}

Тернарные операторы также могут быть вложенными, например:

a ? b ? "a is true, b is true" : "a is true, b is false" : "a is false"

// This is evaluated from left to right and can be more easily seen with parenthesis:

a ? (b ? x : y) : z

// Where the result is x if a && b, y if a && !b, and z if !a

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

Типы expression_if_true и expression_if_false должны быть идентичными или должны быть неявным преобразованием из одного в другое.

condition ? 3 : "Not three"; // Doesn't compile because `int` and `string` lack an implicit conversion.

condition ? 3.ToString() : "Not three"; // OK because both possible outputs are strings.

condition ? 3 : 3.5; // OK because there is an implicit conversion from `int` to `double`. The ternary operator will return a `double`.

condition ? 3.5 : 3; // OK because there is an implicit conversion from `int` to `double`. The ternary operator will return a `double`.

Требования типа и преобразования применяются также к вашим собственным классам.

public class Car
{}

public class SportsCar : Car
{}

public class SUV : Car
{}

condition ? new SportsCar() : new Car(); // OK because there is an implicit conversion from `SportsCar` to `Car`. The ternary operator will return a reference of type `Car`.

condition ? new Car() : new SportsCar(); // OK because there is an implicit conversion from `SportsCar` to `Car`. The ternary operator will return a reference of type `Car`.

condition ? new SportsCar() : new SUV(); // Doesn't compile because there is no implicit conversion from `SportsCar` to SUV or `SUV` to `SportsCar`. The compiler is not smart enough to realize that both of them have an implicit conversion to `Car`.

condition ? new SportsCar() as Car : new SUV() as Car; // OK because both expressions evaluate to a reference of type `Car`. The ternary operator will return a reference of type `Car`.

тип

Возвращает объект System.Type для типа.

System.Type type = typeof(Point)        //System.Drawing.Point      
System.Type type = typeof(IDisposable)  //System.IDisposable
System.Type type = typeof(Colors)       //System.Drawing.Color
System.Type type = typeof(List<>)       //System.Collections.Generic.List`1[T]

Чтобы получить тип времени выполнения, используйте метод GetType для получения System.Type текущего экземпляра.

Оператор typeof принимает имя типа в качестве параметра, который задается во время компиляции.

public class Animal {} 
public class Dog : Animal {}

var animal = new Dog();

Assert.IsTrue(animal.GetType() == typeof(Animal)); // fail, animal is typeof(Dog) 
Assert.IsTrue(animal.GetType() == typeof(Dog));    // pass, animal is typeof(Dog)
Assert.IsTrue(animal is Animal);                   // pass, animal implements Animal

по умолчанию

Тип значения (где T: struct)

Встроенные примитивные типы данных, такие как char , int и float , а также пользовательские типы, объявленные с помощью struct или enum . Их значением по умолчанию является new T() :

default(int)            // 0
default(DateTime)       // 0001-01-01 12:00:00 AM
default(char)           // '\0' This is the "null character", not a zero or a line break.
default(Guid)           // 00000000-0000-0000-0000-000000000000
default(MyStruct)       // new MyStruct()

// Note: default of an enum is 0, and not the first *key* in that enum
// so it could potentially fail the Enum.IsDefined test
default(MyEnum)         // (MyEnum)0

Тип ссылки (где T: класс)

Любой class , interface , массив или тип делегата. Их значение по умолчанию равно null :

default(object)         // null
default(string)         // null
default(MyClass)        // null
default(IDisposable)    // null
default(dynamic)        // null

имя оператора

Возвращает строку, которая представляет неквалифицированное имя variable , type или member .

int counter = 10;
nameof(counter); // Returns "counter"
Client client = new Client();
nameof(client.Address.PostalCode)); // Returns "PostalCode"

Оператор nameof был введен в C # 6.0. Он оценивается во время компиляции, а возвращаемое строковое значение вставляется встроенным компилятором, поэтому его можно использовать в большинстве случаев, где может использоваться константная строка (например, метки case в инструкции switch , атрибуты и т. Д. .). Это может быть полезно в таких случаях, как повышение и регистрация исключений, атрибутов, ссылок на действия MVC и т. Д. ...

?. (Null условный оператор)

6,0

Представлен в C # 6.0 , Null Conditional Operator ?. будет немедленно возвращать значение null если выражение в левой части оценивается как null , а не бросает NullReferenceException . Если его левая часть оценивается как null значение, она рассматривается как нормальная . оператор. Обратите внимание, что поскольку он может возвращать значение null , его возвращаемый тип всегда является типом с null значением. Это означает, что для структурного или примитивного типа он завернут в Nullable<T> .

var bar = Foo.GetBar()?.Value; // will return null if GetBar() returns null
var baz = Foo.GetBar()?.IntegerValue; // baz will be of type Nullable<int>, i.e. int?

Это удобно при запуске событий. Обычно вам придется обернуть вызов события в инструкции if, проверяющей значение null и затем поднять событие, что будет означать возможность гонки. Используя условный оператор Null, это можно зафиксировать следующим образом:

event EventHandler<string> RaiseMe;
RaiseMe?.Invoke("Event raised");

Приращение и уменьшение префиксов и префиксов

Постерическое приращение X++ добавит 1 к x

var x = 42;
x++;
Console.WriteLine(x); // 43

Постфиксный декремент X-- вычитает один

var x = 42
x--; 
Console.WriteLine(x); // 41

++x называется приращением префикса, он увеличивает значение x, а затем возвращает x, в то время как x++ возвращает значение x, а затем увеличивает

var x = 42;
Console.WriteLine(++x); // 43
System.out.println(x); // 43

в то время как

var x = 42;
Console.WriteLine(x++); // 42
System.out.println(x); // 43

оба они обычно используются в цикле for

for(int i = 0; i < 10; i++)
{
}

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

3.0

Оператор => имеет тот же приоритет, что и оператор присваивания = и является право-ассоциативным.

Он используется для объявления лямбда-выражений, а также широко используется с запросами LINQ :

string[] words = { "cherry", "apple", "blueberry" };

int shortestWordLength = words.Min((string w) => w.Length); //5

При использовании в расширениях LINQ или запросах тип объектов обычно может быть пропущен, поскольку он выводится компилятором:

int shortestWordLength = words.Min(w => w.Length); //also compiles with the same result

Общая форма лямбда-оператора следующая:

(input parameters) => expression

Параметры выражения лямбда указаны перед оператором => , а фактическое выражение / оператор / блок, который должен быть выполнен, находится справа от оператора:

// expression
(int x, string s) => s.Length > x

// expression
(int x, int y) => x + y

// statement
(string x) => Console.WriteLine(x)

// block
(string x) => {
        x += " says Hello!";
        Console.WriteLine(x);
    }

Этот оператор может использоваться для простого определения делегатов без написания явного метода:

delegate void TestDelegate(string s);

TestDelegate myDelegate = s => Console.WriteLine(s + " World");

myDelegate("Hello");

вместо

void MyMethod(string s)
{
    Console.WriteLine(s + " World");
}

delegate void TestDelegate(string s);

TestDelegate myDelegate = MyMethod;

myDelegate("Hello");

Оператор присваивания '='

Оператор присваивания = устанавливает значение левого операнда в значение правого операнда и возвращает это значение:

int a = 3;     // assigns value 3 to variable a
int b = a = 5; // first assigns value 5 to variable a, then does the same for variable b
Console.WriteLine(a = 3 + 4); // prints 7

?? Оператор Null-Coalescing

Нуль-Коалесцентный оператор ?? будет возвращать левую сторону, если не null. Если он равен нулю, он вернет правую часть.

object foo = null;
object bar = new object();

var c = foo ?? bar;
//c will be bar since foo was null

The ?? оператор может быть цепным, что позволяет удалить, if проверки.

//config will be the first non-null returned.
var config = RetrieveConfigOnMachine() ??
             RetrieveConfigFromService() ??
             new DefaultConfiguration();


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow