Именованные параметры C# .Net 4.0 и параметры по умолчанию

StackOverflow https://stackoverflow.com/questions/686322

  •  22-08-2019
  •  | 
  •  

Вопрос

Как вы думаете, какую ценность именованные параметры и параметры по умолчанию добавят в C#.Net 4.0?

Как можно было бы их использовать (чего еще не было достигнуто с помощью перегрузки и переопределения)?

Это было полезно?

Решение

Это может упростить конструкторы, особенно для неизменяемых типов (которые важны для многопоточности) – см. здесь для полного обсуждения.Не так приятно, как это должен возможно, но лучше, чем иметь много перегрузок.Очевидно, вы не можете использовать инициализаторы объектов с неизменяемыми объектами, поэтому обычно:

new Foo {Id = 25, Name = "Fred"}

недоступен;Я соглашусь на:

new Foo (Id: 25, Name: "Fred")

Это можно распространить на общую идею упрощения перегрузок, но в большинство случаях я бы предпочел перегрузки, которые рекламируют допустимые комбинации.Конструкторы немного отличаются, IMO, поскольку вы просто (обычно) определяете начальное состояние.

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


Редактировать повторные комментарии;почему они просто не использовали тот же синтаксис, что и атрибуты?Просто – это может быть неоднозначно с другими членами/переменными (что не является проблемой для атрибутов);возьми пример:

[XmlElement("foo", Namespace = "bar")]

который использует один обычный параметр (для ctor, «foo») и одно именованное назначение.Предположим, мы используем это для обычных именованных аргументов:

SomeMethod("foo", SecondArg = "bar");

(который также может быть конструктором;Я использовал метод для простоты)

Сейчас...что, если у нас есть переменная или свойство с именем SecondArg?Это было бы неоднозначно между использованием SecondArg как именованный аргумент для SomeMethod, и присвоение «бара» SecondArg, и передавая «bar» в качестве обычного аргумента.

Для иллюстрации: это допустимо в C# 3.0:

    static void SomeMethod(string x, string y) { }
    static void Main()
    {
        string SecondArg;
        SomeMethod("foo", SecondArg = "bar");
    }

Очевидно, что SecondArg может быть свойством, полем, переменной и т. д.

Альтернативный синтаксис не имеет такой двусмысленности.


Изменить - этот раздел от 280Z28:Извините, что добавил это сюда, но на самом деле это не уникальный ответ, он слишком длинный для комментариев и включает код.Вы намекнули на двусмысленность, но ваш пример не выявил решающего случая.Я думаю, что приведенный вами пример указывает на что-то, что может сбить с толку, но требуемый {} вокруг инициализаторов объектов предотвращает основную синтаксическую двусмысленность.Мое объяснение следующего кода встроено в виде многострочного блочного комментария.

[AttributeUsage(AttributeTargets.Class)]
public sealed class SomeAttribute : Attribute
{
    public SomeAttribute() { }

    public SomeAttribute(int SomeVariable)
    {
        this.SomeVariable = SomeVariable;
    }

    public int SomeVariable
    {
        get;
        set;
    }
}

/* Here's the true ambiguity: When you add an attribute, and only in this case
 * there would be no way without a new syntax to use named arguments with attributes.
 * This is a particular problem because attributes are a prime candidate for
 * constructor simplification for immutable data types.
 */

// This calls the constructor with 1 arg
[Some(SomeVariable: 3)]
// This calls the constructor with 0 args, followed by setting a property
[Some(SomeVariable = 3)]
public class SomeClass
{
}

Другие советы

Это поможет уйти от проблемы предоставления достойного API для работы с приложениями Office!:)

С некоторыми частями API Office все в порядке, но есть крайние случаи, которые явно были разработаны для использования из языка с необязательными/именованными параметрами.Вот почему они должны быть в C#.

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

Рассмотрим класс Exception.Вместо одного конструктора с необязательными аргументами он имеет четыре конструктора для каждой комбинации «имеет сообщение» и «имеет внутреннее исключение».Это нормально, но теперь подумайте, что произойдет, если вы предоставите нулевое значение конструктору, принимающему внутреннее исключение?Действует ли он точно так же, как конструктор без параметра InnerException, что-то вроде конструктора без параметра InnerException, или он выдает исключение нулевой ссылки?

Один конструктор с двумя дополнительными параметрами сделал бы более очевидным, что передача нулевого внутреннего исключения эквивалентна его полному отсутствию.Идеальное место для аргументов по умолчанию.

Также не забывайте, что теперь каждый производный класс Exception также должен включать в себя 4 конструктора, что является бессмысленной проблемой.

Это значительно упростит взаимодействие COM.

До C# 4 VB.Net был гораздо лучшим языком взаимодействия.Без значений по умолчанию у вас есть огромные списки фиктивных параметров ссылок в C#.

Краткость кода — это очевидное, что приходит на ум.Зачем определять несколько перегрузок, если можно определить одну функцию.Кроме того, если у вас есть два параметра одинакового типа, не всегда возможно создать полный набор перегрузок, которые могут вам понадобиться.

Также это не компилируется:

[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
sealed class MyAttribute : Attribute
{
    public MyAttribute(object a = null)
    {

    }
}


class Test
{
    [My] // [My(a: "asd")]
    int prop1 { get; set; }
}

в то время как это делает:

[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
sealed class MyAttribute : Attribute
{
    public MyAttribute()
    {

    }

    public object a { get; set; }
}

class Test
{
    [My] // [My(a=null)]
    int prop1 { get; set; }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top