Ответ 1
Я уверен, что все в порядке, но если вы беспокоитесь, вы всегда можете просто назначить свойства после вызова параметра меньше конструктора.
взгляните на этот пример кода:
public class Comment
{
private Comment()
{ }
public Comment(string text, DateTime creationDate, string authorEmail)
{
Text = text;
CreationDate = creationDate;
AuthorEmail = authorEmail;
}
public virtual string Text { get; private set; }
public virtual DateTime CreationDate { get; set; }
public virtual string AuthorEmail { get; private set; }
}
Я знаю, что считать ошибочной практикой вызов виртуальных функций-членов из конструктора, однако в NHibernate мне нужны виртуальные свойства для поддержки ленивой загрузки. В этом случае считается, что это нормально?
Я уверен, что все в порядке, но если вы беспокоитесь, вы всегда можете просто назначить свойства после вызова параметра меньше конструктора.
Чтобы расширить ответ на Paco:
В большинстве случаев это не повредит. Но если класс наследуется, виртуальный позволяет свойства get/set переопределяться, поэтому поведение больше не полностью инкапсулируется и не контролируется, поэтому теоретически оно может ломаться. FxCop предупреждает об этом, потому что это потенциальная проблема.
Точка FxCop должна помочь предупредить вас о потенциальных проблемах. Неправильно использовать свойства в конструкторе, если вы знаете, кто/что когда-либо наследует от класса, но это не является "лучшей практикой".
Итак, ответ заключается в том, что это нормально, если вы контролируете какое-либо наследование класса. В противном случае не используйте его и напрямую задайте значения полей. (Это означает, что вы не можете использовать автоматические свойства get/set С# 3.0 - вам придется самостоятельно создавать поля для полей свойств.)
Боковое примечание. Лично все мои проекты - это веб-сайты, которые мы размещаем для клиентов. Таким образом, предполагая, что эта настройка остается той же для проекта, чем это стоит компромиссов, чтобы дублировать различные проверки нулевого/аргумента. Но в любом другом случае, когда я не уверен, что мы будем поддерживать полный контроль над проектом и использованием класса, я бы не стал использовать этот ярлык.
В этом примере все в порядке, но это может вызвать проблемы при наследовании класса и переопределении свойств. Как правило, вы можете создавать поля для виртуальных свойств.
Я знаю, что FxCop жалуется, если вы вызываете виртуальный метод в своем конструкторе, но я не знаю, что FxCop говорит, вы вызываете виртуальное свойство в своем конструкторе...
Я бы подумал, что FxCop тоже будет жаловаться, поскольку свойство переводится в метод в IL.
Вы также можете создать свои свойства как "не виртуальные" и просто указать "lazy = false" в вашем "сопоставлении классов" в NHIbernate. Это не повлияет на поведение коллекций с ленивой нагрузкой.
(Я делаю это все время, так как мне не нравится, что моя инфраструктура (NHibernate) требует, чтобы у меня были свойства virtual.
Я также не знаю, важно ли преимущество производительности динамических прокси-серверов в NHibernate).
Я думаю, вы не должны называть его в конструкторе. Вы можете предоставить метод Initialize(), который вы можете вызвать после построения объекта.
В Initialize() вы можете вызвать необходимые виртуальные методы
IMHO лучшей практикой является использование свойств с полями поддержки:
public class Comment
{
private DateTime _creationDate;
private string _text;
private string _authorEmail;
private Comment() { }
public Comment(string text, DateTime creationDate, string authorEmail)
{
_text = text;
_creationDate = creationDate;
_authorEmail = authorEmail;
}
public virtual string Text
{
get { return _text; }
private set { _text = value; }
}
public virtual string AuthorEmail
{
get { return _authorEmail; }
private set { _authorEmail = value; }
}
public virtual DateTime CreationDate
{
get { return _creationDate; }
set { _creationDate = value; }
}
}
Таким образом, вы можете избежать проблем с дочерними классами и больше не видите никаких предупреждений