C #: Как установить значение по умолчанию для свойства в частичном классе?

Я новичок в C #, так что терпите меня ...

Я реализую частичный класс и хочу добавить два таких свойства:

public partial class SomeModel
{
    public bool IsSomething { get; set; }
    public List<string> SomeList { get; set; }

    ... Additional methods using the above data members ...
}

Я хотел бы инициализировать оба элемента данных: IsSomething на True и SomeList на new List<string>(). Обычно я бы делал это в конструкторе, однако, поскольку это частичный класс, я не хочу касаться конструктора (должен ли я?).

Как лучше всего этого добиться?

Спасибо

PS Я работаю в ASP.NET MVC, добавляя функциональность к определенной модели, следовательно, к частичному классу.


person Roee Adler    schedule 13.08.2009    source источник
comment
Это уже значения по умолчанию для этих типов. Вам не нужно ничего делать.   -  person John Saunders    schedule 13.08.2009
comment
Я хочу пояснить. Что, если мне нужен Истинный или новый Список ‹string› ()?   -  person Roee Adler    schedule 13.08.2009
comment
Я отредактировал вопрос, чтобы отразить значения, которые не являются естественными значениями по умолчанию.   -  person Roee Adler    schedule 13.08.2009
comment
Вам нужно будет использовать поле резервного хранилища и инициализировать его встроенным или поместить в конструктор.   -  person Reed Copsey    schedule 13.08.2009
comment
@John: вам не нужно ничего делать - при условии, что вы хотите, чтобы ваши абоненты / клиенты инициализировали свойство SomeList за вас;)   -  person STW    schedule 13.08.2009
comment
@Yooder: Джон ответил, когда был задан вопрос о значениях по умолчанию False и null, в отношении которых он совершенно прав.   -  person Roee Adler    schedule 13.08.2009


Ответы (8)


Обновлено для C # 6

В C # 6 добавлена ​​возможность назначать автоматическим свойствам значение по умолчанию. Значение может быть любым выражением (оно не обязательно должно быть константой). Вот несколько примеров:

// Initialize to a string literal
public string SomeProperty {get;set;} = "This is the default value";

// Initialize with a simple expression
public DateTime ConstructedAt {get;} = DateTime.Now;

// Initialize with a conditional expression
public bool IsFoo { get; } = SomeClass.SomeProperty ? true : false;

Исходный ответ

Автоматически реализуемые свойства могут быть инициализированы в конструкторе класса, но не в самом свойстве.

public SomeModel
{
    IsSomething = false;
    SomeList = new List<string>();
}

... или вы можете использовать свойство с поддержкой поля (немного больше работы) и инициализировать само поле ...

private bool _IsSomething = false;
public bool IsSomething
{
    get { return _IsSomething; }
    set { _IsSomething = value; }
}

Обновление: мой ответ не проясняет проблему принадлежности к частичному классу. Ответ Мердада предлагает решение с использованием частичного метода, что соответствует моему первому предложению. Мое второе предложение об использовании неавтоматически реализуемых свойств (реализованных вручную свойств?) Сработает в этой ситуации.

person STW    schedule 13.08.2009
comment
SomeList = новый список ‹string› ** () **; - person grenade; 13.08.2009
comment
Что касается вашего первого предложения, считается ли это хорошей практикой? Конечно будет проще, но похоже на запах кода ... - person Roee Adler; 13.08.2009
comment
@RaxL Я не понимаю, что такое запах. Логика инициализации - вполне нормальная часть объектно-ориентированной разработки; при условии, что разработчики, работающие над системой, следуют той же практике, я не думаю, что это будет проблемой. - person STW; 13.08.2009
comment
Обратите внимание: добавление любого кода (включая этот ответ) в ваш автоматически сгенерированный класс будет удален после обновления вашей модели. - person H35am; 25.08.2017
comment
@ H35am, вы никогда не должны изменять сгенерированные классы (леса - это совсем другая история - вы никогда не обновляете или повторно генерируете леса) - person STW; 25.08.2017
comment
Но как реализовать свой ответ в частичном классе? Поскольку проблема утверждает, что в автоматически сгенерированном классе Model требуется некоторая функциональность. - person H35am; 25.08.2017

Первое свойство (IsSomething) является логическим. По умолчанию он будет ложным.

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

Если вы хотите использовать значение, отличное от значения по умолчанию, у вас будет два варианта:

Во-первых, используйте резервное хранилище:

private bool isSomething = true;
public bool IsSomething {
    get { return this.isSomething; }
    set { this.isSomething = value; }
}

Второй вариант - добавить в конструктор.

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

person Reed Copsey    schedule 13.08.2009
comment
+1 за указание на различное поведение типов значений / ссылок. - person STW; 13.08.2009

В двух частях частичного класса не может быть двух конструкторов. Однако вы можете использовать частичные методы для выполнения чего-то вроде этого:

// file1:
partial void Initialize();
public Constructor() {
    // ... stuff ... initialize part 1
    Initialize();
}

// file2:
void Initalize() {
    // ... further initializations part 2 might want to do
}

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

person mmx    schedule 13.08.2009
comment
Увы, это не помогает, если часть класса, в которой есть конструктор, является сгенерированным кодом. - person Vaccano; 23.08.2013

ПРЕДУПРЕЖДЕНИЕ для пользователей частичных классов WCF

Если вы пытаетесь добавить свойство в прокси-класс WCF (сгенерированный с помощью Add Service Reference), вы можете быть удивлены, обнаружив, что частные поля не инициализируются, поскольку очевидно никакой конструктор не вызывается.

Если вы попытаетесь сделать это (как предлагается в некоторых других ответах), он никогда не будет вызван:

    private bool _sendEmail = true;

Это не имеет никакого отношения к тому, принадлежит ли поле частичному классу или нет.

Вам нужно добавить [OnDeserialized] , который позволяет выполнять дальнейшую инициализацию объекта. Это часть System.Runtime.Serialization, поэтому полезно только в контексте сериализации при использовании DataContractSerializer.

public partial class EndOfDayPackageInfo
{
    [OnDeserialized()]
    public void Init(StreamingContext context)
    {
        _sendEmail = true;
    }

    private bool _sendEmail;
    public bool SendEmail
    {
        get
        {
            return _sendEmail;
        }
        set
        {
            _sendEmail = value;
            RaisePropertyChanged("SendEmail");
        }
    }

}

Другой подход - «ленивая загрузка» свойства, но этот подход гораздо менее элегантен.

    private bool _sendEmail;
    private bool _sendEmailInitialized;

    public bool SendEmail
    {
        get
        {
            if (!_sendEmailInitialized)
            {
                _sendEmailInitialized = true;
                _sendEmail = true;  // default value
            }

            return _sendEmail;
        }
        set
        {
            if (!_sendEmailInitialized)
            {
                // prevent unwanted initialization if 'set' is called before 'get'
                _sendEmailInitialized = true;
            }

            _sendEmail = value;
            RaisePropertyChanged("SendEmail");
        }
    }
person Simon_Weaver    schedule 01.12.2010
comment
Как интересно. В некотором смысле имеет смысл. - person NotMe; 01.12.2010
comment
да, но сначала очень сбивает с толку. только что обнаружил это сегодня и подумал, что это проблема привязки WPF, пока я, наконец, не понял, что это WCF. оказывается, они вызывают этот метод, который позволяет избежать вызова любого конструктора: msdn.microsoft.com/en-us/library/ - person Simon_Weaver; 01.12.2010
comment
Спасибо, это была моя проблема. - person Dylan Meador; 21.01.2012
comment
что делает метод RaisePropertyChange? это метод из .net framework ?? - person ncubica; 29.11.2012

Для этого используйте не автоматическое свойство, а старый способ

YourType _yourParameter = yourDefaultValue;
public YourType YourParameter
{
   get{return _yourParameter;}
   set{_yourParameter=value;}
}
person Gregoire    schedule 13.08.2009

Для пользователей C # версии 6.0 можно инициализировать свойства следующим образом:

public bool IsSomething { get; set; } = true;
public List<string> SomeList { get; set; } = new List<string>();
person Ant    schedule 16.03.2016

Оба ваших свойства уже будут иметь требуемые значения по умолчанию.

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

person Paul Turner    schedule 13.08.2009
comment
Как указал Рид в своем комментарии, типы значений будут инициализированы значением по умолчанию (0 для int, false для bool ...), но ссылочные типы будут инициализированы значением null / Nothing. Итак, в его случае IsSomething = false и SomeList = null - person STW; 13.08.2009
comment
@Yooder: этот ответ был предоставлен, когда вопрос все еще задавал значения по умолчанию False и null. Пожалуйста, отзовите свой -1, это несправедливо по отношению к @Programming Hero - person Roee Adler; 13.08.2009
comment
Перемещение ворот в середине игры? Нечестно! - person Paul Turner; 14.08.2009

 private bool _InternalUserContactUpdate = false;
        public bool InternalUserContactUpdate
        {
            get { return _InternalUserContactUpdate; }
            set { _InternalUserContactUpdate = value; }
        }

Затем, когда вы хотите переопределить значение по условию,

if(!objUserModel.FirstName.ToLower().Equals(entry.Key[0].Attributes.Contains("firstname").ToString().ToLower()))
        {
             objUserModel.InternalUserContactUpdate= true;
        }

Надеюсь, это поможет

person Subhamay    schedule 13.08.2017