Имеют ли свойства только для записи практическое применение? - PullRequest
48 голосов
/ 06 февраля 2010

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

В C # - и, возможно, во многих других языках, я помню, что Delphi разрешал вам делать это тоже - законно писать этот синтаксис:

class WeirdClass
{
    private void Hello(string name)
    {
        Console.WriteLine("Hello, {0}!", name);
    }

    public string Name
    {
        set { Hello(name); }
    }
}

Другими словами, свойство имеет сеттер , но не геттер , оно только для записи .

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

CS83417: Свойство «Имя» выглядит совершенно бесполезным и глупым. Плохой программист! Попробуйте заменить методом.

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

Существуют ли в реальной жизни примеры свойств только для записи, которые либо нельзя заменить прямыми вызовами методов, либо стали бы менее интуитивными?

Ответы [ 14 ]

0 голосов
/ 20 ноября 2015

Я знаю, что это было здесь в течение долгого времени, но я сталкивался с этим и имею действительный (imho) вариант использования:

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

public int MyFancyWepapiMethod([FromBody]CallParams p) {
    return p.MyIntPropertyForAjax.HasValue ? p.MyIntPropertyForAjax.Value : 42;
}

public class CallParams
{
    public int? MyIntPropertyForAjax;

    public object TryMyIntPropertyForAjax
    {
        set
        {
            try { MyIntPropertyForAjax = Convert.ToInt32(value); }
            catch { MyIntPropertyForAjax = null; }
        }
    }
}

На стороне JavaScript вы можете просто заполнить параметры, включая проверку:

var callparameter = {
    TryMyIntPropertyForAjax = 23
}

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

0 голосов
/ 08 марта 2015

Я недавно работал над приложением, которое обрабатывает пароли. (Обратите внимание, что я не утверждаю, что следующее - хорошая идея; я просто описываю то, что я сделал.)

У меня был класс, HashingPassword, который содержал пароль. Конструктор взял пароль в качестве аргумента и сохранил его в закрытом атрибуте. Учитывая один из этих объектов, вы можете либо получить соленый хеш для пароля, либо сравнить пароль с данным соленым хешем. Конечно, не было никакого способа получить пароль от объекта HashingPassword.

Итак, у меня был какой-то другой объект, я не помню, что это было; давайте представим, что это был защищенный паролем банан. Класс Banana имел свойство только для набора, называемое Password, которое создавало HashingPassword из заданного значения и сохраняло его в закрытом атрибуте Banana. Поскольку password атрибут HashingPassword был закрытым, не было никакого способа написать геттер для этого свойства.

Так почему же у меня есть свойство только для набора с именем Password вместо метода с именем SetPassword? Потому что это имело смысл. Фактически эффект заключался в установке пароля для Banana, и если бы я хотел установить пароль для объекта Banana, я бы ожидал сделать это, установив свойство, а не вызывая метод.

Использование метода с именем SetPassword не имело бы серьезных недостатков. Но я также не вижу существенных преимуществ.

0 голосов
/ 06 февраля 2010

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

Гипотетический случай:

CommunicationDevice.Response = "Hello, World" 

вместо

CommunicationDevice.SendResponse("Hello, World")

Основной задачей будет выполнение побочных эффектов ввода-вывода или проверки.

Интересно, что VB .NET даже получил свое собственное ключевое слово для этого странного вида свойств;)

Public WriteOnly Property Foo() As Integer
   Set(value As Integer)
     ' ... '
   End Set
End Property

хотя многие свойства «только для записи» извне действительно имеют частный получатель.

0 голосов
/ 06 февраля 2010

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

Например:

class SomeClass {
    private int _someVar;

    SomeClass(int someVar) {
        if(someVar > 0) _someVar = someVar;
    }

    public int SomeVar {
        set { if(value > 0) _someVar = value; }
    }

     public string SomeFunction(){
       return "This is an important function that uses _someVar " + _someVar;
     }
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...