Ошибка инициализации принудительной инициализации объекта - PullRequest
3 голосов
/ 29 марта 2012

Можно ли применять правила или выдавать ошибку при использовании инициализаторов объектов в C #? Я хотел бы выдать ошибку или предупреждение компилятора, если объект инициализирован, но отсутствует определенное свойство.

public class Party
{
    public string Name { get; set; }
    public string Date { get; set; }
    public Location Location { get; set; }
}

public class SignUpForParty
{
    public void DoSomething()
    {
        Party party = new Party()
        {
            Name = "New Years Party!",
            Date = "Dec 31, 1999"
            // Show WARNING/ERROR here because no Location given
        };
    }
}

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

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

Obj p = new Obj(1, 2, 3,...n); // too many properties to be pretty

Ответы [ 5 ]

4 голосов
/ 29 марта 2012

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

Инициализаторы объектов действительно не должны рассматриваться как альтернатива написанию конструктора.

Вы всегда должны включать конструкторы в свои типы, если выесть требования, как это.Хорошей идеей является создание набора конструкторов по умолчанию (или использование необязательных аргументов для одного конструктора), которые по крайней мере обеспечивают гарантию того, что объект всегда будет создан в допустимом значимом состоянии.

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

3 голосов
/ 29 марта 2012

Вы не можете принудительно инициализировать каждое свойство с помощью инициализатора объекта.

Даже если бы вы могли, потребитель объекта мог бы предоставить значения по умолчанию (0, ноль, ...). В зависимости от ваших потребностей рассмотрите возможность проверки состояния объекта в ключевые моменты времени (например, до того, как оно может быть сохранено в базе данных).

Если вы идете по этому пути, взгляните на интерфейс IDataErrorInfo .

2 голосов
/ 29 марта 2012

Если ваш тип недействителен, когда заданы только 2 свойства, вам нужно исправить свой дизайн, а не выдавать ошибку.

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

Если это не так, тогда я предлагаю вам предоставить конструктор, который заставляет меня указывать все три значения. Да, я все еще могу использовать (null, null, null), но вы можете проверить это и выдать ошибку.

Кроме того, если PropertyA зависит от PropertyB, то либо

A) Только у одного из них должен быть сеттер, или

B) Должна быть логика в установщике каждого для правильной инициализации другого после изменения значения.

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

Obj p = новый Obj (1, 2, 3, ... n); // слишком много свойств, чтобы быть симпатичными

Код не должен быть «красивым», он должен работать. Даже тогда конструктор, который принимает несколько аргументов, «уродлив»? А? Не покупайте ерунду для хипстеров, пишите код, который работает и работает хорошо.

0 голосов
/ 29 марта 2012

Как насчет Кодовых контрактов ?.Это подтвердит не только то, что вы присвоили значение, но вы также можете указать допустимые диапазоны.

Или для проверки во время выполнения только с отладочными сборками можно использовать Debug.Assert (...) призывает достичь того же, что и выше.

0 голосов
/ 29 марта 2012

Единственный способ увидеть, как это реализовано, - это если было какое-то событие (или эквивалент), которое было вызвано, когда инициализатор объекта был завершен. В настоящее время существует запрос на подключение для чего-либо на этот счет.

К сожалению, я не сделал сокращение для .NET 4.5:

Спасибо за ваше предложение.

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

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

Еще раз спасибо!

Мадс Торгерсен, язык C # PM

Может быть, он попадет в .NET 5+.

...