Как лучше всего изменить и вернуть аргумент C #? - PullRequest
5 голосов
/ 22 сентября 2011

Мне нужно взять виджет, в котором уже установлено несколько значений свойств. Мне нужно изменить имя виджета. Меня тянет к Варианту 3, но мне трудно объяснить, почему.

public void Do(Widget widget) { // 1
    widget.Name = "new name";
}

public void Do(ref Widget widget) { // 2
    widget.Name = "new name";
}

public Widget Do(Widget widget) { // 3
    widget.Name = "new name";
    return widget;
}

Я бы хотел сыграть в «Адвоката дьявола» с несколькими вопросами и собрать ответы, чтобы объяснить, почему меня привлекли к варианту 3.

Вариант 1: Почему не просто изменить переданный виджет? Вы только «возвращаете» один объект. Почему бы просто не использовать переданный объект?

Вариант 2: Почему не возврат недействителен? Почему бы просто не сообщить в подписи, что вы будете использовать фактический указатель памяти на сам объект параметра?

Вариант 3: Тебе не странно, что ты возвращаешь тот же самый объект, который передаешь?

Ответы [ 4 ]

12 голосов
/ 22 сентября 2011

Вариант 1: Это наиболее распространенный подход - вам не нужен ref, если вы не хотите изменять ссылку .Убедитесь, что вы правильно назвали свой метод, так что ожидается, что переданный объект действительно будет изменен.

Опция 2: Это полезно, только если вы хотите изменить переданную ссылкусам , т. е. создать новый экземпляр Widget или установить ссылку для указания на существующий виджет (это может быть полезно, если вы хотите сохранить общее количество экземпляров низким, если все они имеют одинаковые свойства, см. Шаблон Flyweight , обычно возвращаемые виджеты должны быть неизменяемыми в этом случае, и вместо этого вы должны использовать фабрику).В вашем случае это не представляется целесообразным.

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

6 голосов
/ 22 сентября 2011

Вариант 1:

Fine. Именно то, что я бы использовал. Вы можете изменять содержимое виджета, но не сам виджет.

Вариант 2:

Нет. Нет. Вы сами не изменяете ссылку, поэтому вам не нужно использовать ref. Если вы изменили саму ссылку (например, widget = new Widget(), то out / ref - правильный выбор, но по моему опыту это редко требуется.

Вариант 3:
Аналогичен варианту 1. Но может быть объединен в свободный интерфейс API. Лично мне это не нравится. Я использую эту подпись, только если я возвращаю копию и оставляю оригинальный объект без изменений.


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

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

4 голосов
/ 22 сентября 2011

На самом деле нет никакой функциональной разницы между 3 вариантами. (Существуют различия, но ни один из них не имеет отношения к вашему вопросу.) Проще говоря - используйте вариант 1.

1 голос
/ 22 сентября 2011

Я думаю, что Вариант 1 и Вариант 3 являются жизнеспособными вариантами. Вариант 3 имеет то преимущество, что самодокументируется, поскольку подразумевает, что вы модифицируете виджет в методе. Я думаю, что худший вариант - это вариант 2. Ключевое слово ref для меня подразумевает, что вы изменяете ссылку на объект, чего вы наверняка не делаете.

...