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

Какая польза от шаблонов var в С# 7?

Я не понимаю пример использования шаблонов var в С# 7. MSDN:

Совпадение шаблона с шаблоном var всегда выполняется успешно. Его синтаксис

expr is var varname

где значение expr всегда назначается локальной переменной с именем varname. varname - статическая переменная того же типа, что и expr.

Пример на MSDN довольно бесполезен, на мой взгляд, особенно потому, что if is избыточен:

object[] items = { new Book("The Tempest"), new Person("John") };
foreach (var item in items) {
  if (item is var obj)
    Console.WriteLine($"Type: {obj.GetType().Name}, Value: {obj}"); 
}

Здесь я не вижу никаких преимуществ, вы могли бы иметь то же самое, если бы вы напрямую обращались к item переменной цикла, который также относится к типу Object. if это сбивает с толку, потому что это никогда не false.

Я мог бы использовать var otherItem = item или использовать item разному. Может ли кто-нибудь объяснить прецедент лучше?

4b9b3361

Ответ 1

Шаблон var очень часто обсуждался в репозитории языка С#, учитывая, что он не совсем ясно, каков его вариант использования, и учитывая тот факт, что is var x не выполняет нулевую проверку, а is T x делает, что делает его кажущимся бесполезным.

Однако на самом деле это не означает, что obj is var x. Он предназначен для использования, когда левая сторона не является переменной сама по себе.

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

В следующем примере объявляется функция Deriv для построения производной функции с использованием сопоставления структурных шаблонов в дереве выражений:

Expr Deriv(Expr e)
{
    switch (e) {
        // …
        case Const(_): return Const(0);
        case Add(var Left, var Right):
            return Add(Deriv(Left), Deriv(Right));
        // …
}

Здесь шаблон var может использоваться внутри структур для "вытаскивания" элементов из структуры. Аналогично, следующий пример упрощает выражение:

Expr Simplify(Expr e)
{
    switch (e) {
        case Mult(Const(0), _): return Const(0);
        // …
        case Add(Const(0), var x): return Simplify(x);
    }
}

Как пишет gafter, идея состоит в том, чтобы иметь соответствие свойств, позволяющее:

if (o is Point {X is 3, Y is var y})
{ … }

Ответ 2

Не проверяя примечания по дизайну на Github, я бы предположил, что это было добавлено больше для согласованности с switch и в качестве шага для более сложных случаев сопоставления шаблонов,

Из оригинального Whats New в С# 7.0 сообщение:

Var шаблонов формы var x (где x - идентификатор), которые всегда совпадают, и просто поместите значение ввода в новую переменную x с тем же типом, что и вход.

И недавний диссидентский пост Сергея Теплякова:

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

public void VarPattern(IEnumerable<string> s)
{
    if (s.FirstOrDefault(o => o != null) is var v
        && int.TryParse(v, out var n))
    {
        Console.WriteLine(n);
    }
}

Предупреждение до этого фрагмента также важно:

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

По словам Кристиана Нагеля:

Преимущество состоит в том, что переменная, объявленная с ключевым словом var, имеет реальный тип объекта,

Ответ 3

Единственное, о чем я могу думать, - это если вы обнаружите, что вы написали два одинаковых блока кода (например, один switch), один для expr is object a а другой для expr is null.

Вы можете комбинировать блоки, переключаясь на expr is var a.

Он также может быть полезен в сценариях генерации кода, где по какой-то причине вы уже закрепили себя в углу и всегда ожидаете генерировать совпадение с шаблоном, но теперь хотите создать шаблон "match all".

Ответ 4

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

        var sample = new(int id, string name, int age)[] { 
                                                          (1, "jonas", 50),                                                                                                                            
                                                          (2, "frank", 48) };

        var f48 = from s in sample 
                  where s.age == 48 
                  select new { Name = s.name, Age = s.age };

        switch(f48.FirstOrDefault())
        {
            case var choosen when choosen.Name == "frank":
                WriteLine(choosen.Age);
                break;
            case null:
                WriteLine("not found");
                break;
        }