Когда аргументы называются полезными?
Есть ли какой-либо случай в коде С#, где недостаточно аргументов позиции?
Я действительно не вижу преимуществ именованных аргументов, напротив, я вижу, как чрезмерное использование именованных аргументов может затруднить чтение кода? Поэтому мой вопрос: зачем кому-то использовать их и как он может помочь в написании лучшего кода, поскольку я уверен, что они не были реализованы без причины?
Это выглядит чище для меня:
private void Foo(1, true);
то
private void Foo(bar: 1, baz: true);
Ответы
Ответ 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);
Конечно, это компилируется, но результирующие данные теперь испорчены, потому что
- изначально порядок был неправильным, но все еще работал правильно из-за имен
- кто-то удалил имена, но не проверил порядок
Не уверен, что вы можете винить только одного разработчика...