Передача по ссылке: что является более читабельным / правильным?

У меня есть следующий класс:

public class Person
{
     public String Name { get; set; }
}

У меня есть метод, который принимает Person и String в качестве параметров:

public void ChangeName(Person p, String name)
{
     p.Name = name;
}

поскольку Person был передан по ссылке, это должно изменить Name пропущенного экземпляра.

Но является ли этот метод более читабельным, чем приведенный выше?

public Person ChangeName(Person p, String name)
{
     p.Name = name;
     return p;
}

8 ответов

Решение

Это более читабельно? Нет. На самом деле вы можете причинять им больше вреда.

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

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

Итак, вот моя рекомендация для этого метода:

public static void ChangeName(Person p, String name)
{
    p.Name = name;
}

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

Нет ничего правильного / неправильного в любом подходе. Зависит от того, что нужно вашей программе.

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

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

Делайте это, только если вам действительно нужна гибкость.

Я бы посоветовал вам использовать один из следующих способов для лучшей читабельности:

public static void ChangeName(Person p, String name)
{
    p.Name = name;
}

public static Person WithName(Person p, String name)
{
    return new Person(p) { Name = name };    
}

Второй обрабатывает объект Person как неизменный и не изменяет состояние объекта. Функция ChangeName явно изменяет состояние входного объекта. Я думаю, что важно проводить четкое различие между двумя типами методов. Хорошее практическое правило заключается в том, что метод не должен изменять состояние объекта и возвращать его одновременно.

В случае, который вы описали, я бы сказал, что нет. Не совсем понятно, что вы пытаетесь сделать с помощью этого метода. Просто используйте объект и установите свойство. Вставка метода в путь выполнения только усложняет понимание и создает другую зависимость от объекта Person и его базового значения.

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

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

Я верю, что ваш второй подход не более читабелен, ЯГНИ. Но если вы измените это так

public static class PersonExtensions 
{
public static Person ChangeName(this Person p, String name)
{
 p.Name = name;
 return p;
}

у вас будет метод расширения для свободного интерфейса а-ля

new Person().ChangeName("Peter Smith").SendEmail().Subject("Test Mail").Receiver("....)

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

Глядя на код, почему вы не используете свойство?

public string Name
{
   set {name = value;}
   get { return name; }
}

РЕДАКТИРОВАТЬ: Авто реализованные свойства

public string Name
{
   set;
   get;
}
Другие вопросы по тегам