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

Когда аргументы называются полезными?

Есть ли какой-либо случай в коде С#, где недостаточно аргументов позиции? Я действительно не вижу преимуществ именованных аргументов, напротив, я вижу, как чрезмерное использование именованных аргументов может затруднить чтение кода? Поэтому мой вопрос: зачем кому-то использовать их и как он может помочь в написании лучшего кода, поскольку я уверен, что они не были реализованы без причины?

Это выглядит чище для меня:

private void Foo(1, true);

то

private void Foo(bar: 1, baz: true);
4b9b3361

Ответ 1

Именованные аргументы предназначены для повышения удобочитаемости. Например, я просто использовал один как таковой

public void MarkAsDone(bool skipped) {}

Теперь, вызывая метод без имени, мы имеем двусмысленность

MarkAsDone(true); //does true mean that it is successfully done?

Что может быть разрешено путем уточнения с именем

MarkAsDone(skipped: true);

Я думаю, что использование именованного параметра делает код клиента менее двусмысленным.

Часть из того, что они могут использоваться, чтобы однозначно идентифицировать необязательный параметр, когда там более одного с тем же типом

MarkAsDone(int first, int second=0, int third=0) {}

///

MarkAsDone(1, third: 3);

Ответ 2

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

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

Посмотрите на сайт вызова:

something.OpenFile(documentPath, true);

Что это будет делать? Он откроется documentPath. И сделать что-то еще? Что еще? Я не помню, хотя я написал OpenFile только неделю назад.

Вот три разных примера для OpenFile, которые относительно реалистичны.

void OpenFile(string path, bool shouldOverwrite)
void OpenFile(string path, bool preserveExisting)
void OpenFile(string path, bool enableWriting)

С именованными параметрами мы можем сделать сайты вызовов ясными:

something.OpenFile(documentPath, shouldOverwrite: false);

Довольно ясно, что файл не будет перезаписан.

something.OpenFile(documentPath, preserveExisting: false);

Довольно ясно, что файл будет перезаписан, если потребуется.

И, наконец, мы имеем:

something.OpenFile(documentPath, enableWriting: false)

Довольно ясно, что файл будет открыт только для чтения.

Может ли этот конкретный пример быть разрешен с чем-то другим, подобным перечислению? Да. Вы всегда можете изменить код? Нет. У всех остальных одинаковая ненависть к параметрам bool, которые я делаю? №: -)

Вы можете сделать это с помощью названных параметров? Да. Помогают ли полезные локальные переменные? Потрясающе.

Ответ 3

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

private void ShowPopup(FrameworkElement content, 
                         string title = "My Application", 
                         bool isDialog = true,
                         double? width = null, 
                         double? height = null, 
                         double? offsetX = null, 
                         double? offsetY = null, 
                         bool isTransparent = false,
                         ... etc) 

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

PopupHelper.ShowPopup(_view, isTransparent: true);

или что-то в этом роде.

Ответ 4

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

Для такого метода:

public void Do(Thing thing, bool doItTwice = false, bool logResults = false,
               string something = null, bool makeTeaAfterwards = false)

Затем вы должны использовать именованные параметры, чтобы не указывать весь список:

Do(thing, makeTeaAfterwards: true);

Вместо

Do(thing, false, false, null, true);

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

Ответ 5

Я не уверен, но я думаю, что вы неправильно поняли именованные параметры.

Пожалуйста, смотрите: http://www.dotnetperls.com/named-parameters

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

Method1(test1: 1, ..., test20: 10);

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

Ответ 6

Если у вас есть подпись метода, например:

private void Foo(int bar, bool baz);

то именованные аргументы не помогают, нет.

Но представьте себе подпись метода, например:

private void Foo(bool bar, int baz=0, int qux=0);

И скажите, что вы хотели передать значение по умолчанию baz, но параметр для qux, а затем аргументы здесь:

Foo(true, qux:1);

Ответ 7

В эти дни С# поддерживает необязательные параметры, например:

public void Dance(string song = "makarena",
                  string location = "your house",
                  string performer = "Michael",
                  DateTime? date = null,
                  int milliseconds = 0,
                  Action callback = null)
{
    ///party code
}

Теперь вы можете вызвать его, пропустив некоторые аргументы (в любом порядке):

Dance(location : "my house", date : DateTime.Now, performer : "Christina");

Я проверил код. К сожалению, я не видела сексуальный танец Кристины, потому что я забыла установить параметр в миллисекундах: P (Не по моей вине, но из тех, кто делал API, почему они делают необязательные миллисекунды?: P).

Мое мнение таково, что истинная ценность этого в COM Interop и подобных ситуациях. Например, в объектах Office COM есть несколько методов с множеством аргументов, которые без них являются проблемой (например, Word.Documents.Open).

Ответ 8

Ответ на аналогичный вопрос, который был удален, поэтому я опубликую его здесь. Я думаю, что аргумент Com Call еще не включен:

Существует одна или две веские причины использовать именованные параметры.

1) При использовании вызовов Com/Необязательных параметров

Представьте себе следующее:

var excelApp = new Microsoft.Office.Interop.Excel.Application();
excelApp.Workbooks.Add();
excelApp.Visible = true;
var myFormat =
Microsoft.Office.Interop.Excel.XlRangeAutoFormat.xlRangeAutoFormatAccounting1;

excelApp.get_Range("A1", "B4").AutoFormat(myFormat, Type.Missing, 
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

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

Однако вы можете значительно упростить вызов AutoFormat, используя именованные и необязательные аргументы, представленные в С# 4.0.

excelApp.Range["A1", "B4"].AutoFormat( Format: myFormat );

2) Именованные параметры могут создавать лучший/более четкий код

File.Copy("source.txt", "destination.txt", true);

Если вы не знаете разработчика этого метода, вы можете только догадываться о том, для чего нужен последний Boolean-параметр. С указанными параметрами С# 4.0 этот код можно записать так, чтобы более четко выразить намерение:

File.Copy("source.txt", "destination.txt", overwrite: true);

3) Он продает код

вместо этого

Person person = new Person();
person.FirstName = "John";
person.LastName = "Smith";
person.DateOfBirth = new DateTime(1970, 1, 1);

вы можете использовать (в зависимости от предпочтений читаемости)

Person person = new Person() { FirstName = "John", LastName="Smith", DateOfBirth = new DateTime(1970, 1, 1)};

Ответ 9

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

Например,

int Duration(d1,d2)

Это от d1 до d2 или d2 - d1? Intellisense может сказать вам, имеют ли аргументы хорошие имена, а также документация правильная и актуальная. Или вы можете посмотреть на код...

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

Ответ 10

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

// unnamed:
collection.remove(true, true, false)
// named:
collection.remove(old:true, deprecated:true, unused:false);

Есть много других способов достичь этого, конечно, из побитовые флаги для intellisense. Но при программировании на Python я использую named params довольно выделять. Конечно, нет сильной печати и худшего инструмента.

Ответ 11

  • Хорошей практикой является сохранение аргументов в правильном порядке.
  • Хорошей практикой является не удалять имена вслепую, когда вы читаете из других источников.

Пример функции:

public void TrackDataChange(IEntity oldData, IEntity newData)

Старый звонок:

dataTrackerService.TrackDataChange(newData: valuesFromClient.ToEntity(), oldData: valuesFromDb.ToEntity())

Новый звонок:

var oldData = new ValueEntityConverter(valuesFromDb).Entity;
var newData = new ValueEntityConverter(valuesFromClient).Entity;

dataTrackerService.TrackDataChange(newData, oldData);

Конечно, это компилируется, но результирующие данные теперь испорчены, потому что

  • изначально порядок был неправильным, но все еще работал правильно из-за имен
  • кто-то удалил имена, но не проверил порядок

Не уверен, что вы можете винить только одного разработчика...