2009-08-13 17 views
18

Jestem bardzo nowe do C# tak proszę nosić ze mną ...C#: Jak ustawić wartość domyślną dla właściwości w klasie częściowej?

Jestem realizacji częściowej klasy, i chciałbym dodać dwie właściwości tak:

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

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

chciałbym zainicjuj oba elementy danych: IsSomething na True i SomeList na new List<string>(). Zwykle robiłbym to w konstruktorze, jednak ponieważ jest to klasa cząstkowa, nie chcę dotykać konstruktora (czy powinienem?).

Jaki jest najlepszy sposób, aby to osiągnąć?

Dzięki

PS pracuję w ASP.NET MVC, dodając funkcjonalność Do pewnego modelu, stąd częściowe klasy.

+2

To są alniki dy domyślne wartości dla tych typów. Nie musisz nic robić. –

+0

Chcę wyraźne. Co się stanie, jeśli chcę mieć "True" lub "nową listę ()"? –

+1

Edytowałem pytanie, aby odzwierciedlić wartości, które nie są "naturalnymi" wartościami domyślnymi. –

Odpowiedz

34

Aktualizacja dla C# 6

C# 6 wprowadził możliwość przypisania wartości domyślnej Aby automatycznie właściwości. Wartość może być dowolnym wyrażeniem (nie musi być stałą). Oto kilka przykładów:

// 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; 

Original odpowiedzi

Automatycznie wdrożone właściwości mogą być inicjowane w konstruktorze klasy, ale nie na samej propery.

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

... czy można użyć właściwości pola oparciem (nieco więcej pracy) i inicjować samego pola ...

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

Aktualizacja: Moja powyższa odpowiedź nie wyjaśnia kwestia tego jest w częściowej klasie. Mehrdad's answer oferuje rozwiązanie zastosowania metody częściowej, co jest zgodne z moją pierwszą sugestią. Moja druga sugestia użycia nieautomatycznie zaimplementowanych właściwości (ręcznie zaimplementowanych właściwości?) Będzie działać w tej sytuacji.

+0

SomeList = new List **() **; – grenade

+0

Co do pierwszej sugestii, czy uważa się to za "dobrą praktykę"? Z pewnością będzie łatwiej, ale czuje się jak "zapach kodu" ... –

+0

@RaxL Jestem na ogrodzeniu o tym zapachu. Logika inicjalizacji jest dość normalną częścią rozwoju OO; pod warunkiem, że programiści pracujący w systemie będą postępować zgodnie z tymi samymi praktykami, nie będę tego myślał. – STW

8

Pierwsza właściwość (IsSomething) jest wartością logiczną. Domyślnie będzie to fałsz.

Druga właściwość, ponieważ jest to typ odniesienia, domyślnie będzie miała wartość null bez żadnego wysiłku z Twojej strony. Nie trzeba dotykać konstruktora, ponieważ typy odniesienia (klasy) będą automatycznie uruchamiane jako null w .NET.

Jeśli chcesz użyć wartości niż domyślny, to masz dwie opcje -

Najpierw użyj pola przechowywania Podłoże:

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

Druga opcja - dodaj ją do konstruktora.

Należy zauważyć, że pierwsza opcja nie ma dodatkowego obciążenia - w zasadzie jest to, co robi kompilator podczas korzystania z właściwości automatycznej.

+0

+1 za wskazanie różnych zachowań wartości/typów odniesienia. – STW

1

Obie twoje właściwości będą już miały domyślne wartości, których potrzebujesz.

Nie ma nic złego w posiadaniu konstruktora w klasie częściowej. Częściowe klasy nie są w żaden sposób wyjątkowe, pomijając fakt, że ich kod źródłowy jest rozłożony na wiele plików/deklaracji.

+1

Jak zauważył Reed w swoim komentarzu, typy-wartości zostaną zainicjowane z wartością domyślną (0 dla int, false dla bool ...), ale typy odniesienia zostaną zainicjowane na wartość null/Nothing. Tak więc w jego przypadku IsSomething = false i SomeList = null – STW

+0

@Youer: ta odpowiedź została dostarczona, gdy pytanie nadal zawierało pytania o wartości domyślne False i null. Proszę wycofać swoje -1, to nieuczciwe dla @Programming Hero –

+0

Przeniesienie postów na bramkę w połowie gry? Nie fair! –

5

Nie można mieć dwóch konstruktorów w dwóch częściach klasy częściowej. Jednakże, można użyć partial methods osiągnąć coś podobnego:

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

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

Jeśli żadna część częściowej klasy definiuje metodę częściowego, wszystkie połączenia z nim będzie pominięty.

+0

Niestety, to nie pomoże, jeśli część klasy, która ma konstruktora, jest generowany kod. – Vaccano

4

Do tego, nie należy używać automatycznego miejscu, ale po staremu

YourType _yourParameter = yourDefaultValue; 
public YourType YourParameter 
{ 
    get{return _yourParameter;} 
    set{_yourParameter=value;} 
} 
5

ostrzeżenie dla użytkowników WCF klas częściowe

Jeśli próbujesz dodać obiekt do pełnomocnika WCF class (generowany przez Add Service Reference) możesz być zaskoczony tym, że prywatne pola nie zostały zainicjalizowane, ponieważ podobno jest no constructor at all is called.

Jeśli spróbujesz to zrobić (jak sugerowano w niektórych innych odpowiedzi) nie będzie nigdy się nazywa:

private bool _sendEmail = true; 

To nie ma nic wspólnego z tym, czy pole jest w częściowej klasy, czy nie.

Co musisz zrobić, to dodać atrybut [OnDeserialized], który umożliwia dalszą inicjalizację obiektu. Jest to część System.Runtime.Serialization, więc jest przydatna tylko w kontekście serializacji podczas korzystania z 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"); 
     } 
    } 

}

Innym podejściem jest „leniwe” obciążenia nieruchomości - ale takie podejście jest znacznie mniej eleganckie.

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"); 
     } 
    } 
+0

Jak interesujące. Ma sens w pokrętny sposób. – NotMe

+0

ya ale bardzo mylące na początku. Właśnie odkryłem to dzisiaj i pomyślałem, że to był problem wiążący WPF, aż w końcu zrozumiałem, że to był WCF. Okazuje się, że nazywają tę metodę, która omija wywołanie dowolnego konstruktora: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatterservices.getuninitializedobject.aspx –

+0

Dzięki, to był dokładnie mój problem. –

2

Dla użytkowników wersji 6.0 C#, jest to możliwe, aby zainicjować właściwości tak:

public bool IsSomething { get; set; } = true; 
public List<string> SomeList { get; set; } = new List<string>(); 
0
private bool _InternalUserContactUpdate = false; 
     public bool InternalUserContactUpdate 
     { 
      get { return _InternalUserContactUpdate; } 
      set { _InternalUserContactUpdate = value; } 
     } 

Potem, gdy chcesz nadpisać wartości pod warunkiem,

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

Mam nadzieję, że to pomoże