2017-02-17 1 views
0

Freunde, Ich möchte wissen, warum folgender Code für List<int> und nicht für List<string> funktioniert. Wenn ich die Liste im Getter der Eigenschaft initialisiere, funktioniert es nicht. Wenn ich im Konstruktor initialisiere, funktioniert es und auch wenn ich eine Liste in der aufrufenden Klasse erstelle, funktioniert es.Kann Element nicht zu einer Liste hinzufügen, die in einer anderen Klasse initialisiert wurde

public class MyClass 
{ 
    private List<int> _ints; 
    private static List<string> _strings; 

    public MyClass() 
    { 
     _ints = new List<int>(); 
    } 
    public List<int> Ints 
    { 
     get 
     { 
      return _ints; 
     } 
     set 
     { 
      _ints = value; 
     } 
    } 

    public List<string> Strings 
    { 
     get 
     { 
      return _strings ?? new List<string>(); 
     } 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 

     MyClass mc = new MyClass(); 
     // This works 
     // mc.Ints = new List<int>(); 
     // This works   
     mc.Ints.Add(1); 
     // This does not 
     mc.Strings.Add("Krishna"); 
    } 
} 
+0

Sie nie zu einem instantiierten '' Liste _strings' zuordnen ' – Jonesopolis

+0

Sie sind nicht Zugang In einer initialisierten Liste von Strings sehen Sie sich den Unterschied an, wie Sie mit "Ints" interagiert haben und wie Sie mit "Strings" interagiert haben ... –

+0

Eine zusätzliche Frage? Warum sind '_strings'' statisch'? –

Antwort

1

Diese mc.Strings.Add("Krishna"); wird nicht funktionieren, weil Sie neue List<string> kommen jedes Mal, wenn Sie mc.Strings nennen. Um zu erklären, es in mehr Details:

MyClass mc = new MyClass(); // create new instance of MyClass and store it in the "mc" variable 
mc // Direct call to the instance 
    .Strings // Direct call to MyClass Strings property 
     // inside Strings property : 
     // return _strings ?? new List<string>(); 
     // meaning that if "_strings" member field is null 
     // return new instance of that property's type 
    .Add("abc"); // adds "abc" to the "forgotten" instance of List<string> 

Einfach gesagt Sie das gleiche tun, wie Sie nennen würde:

new List<string>().Add("abc"); 

Um dies fixiert können Sie Einzeiler verwenden (die man natürlich versucht) wie diese:

return _strings ?? (_strings = new List<string>()); 

Or if-Anweisung:

if(_strings == null) 
    _strings = new List<string>(); 

return _strings; 
+0

Danke Rogalski. Ich hatte den Eindruck, dass Return _strings ?? neue Liste ()); wird das Objekt behalten. Sieht so aus, als würde immer ein neues Objekt erstellt. –

4

Sie initialisiert die Variable nicht auf dem Getter, wenn die Variable ist null Sie eine neue Liste erstellen, aber Sie speichern nicht den Verweis auf sie.

Code Um dies zu ändern:

public List<string> Strings 
{ 
    get 
    { 
     if(_strings == null) 
      _strings = new List<string>(); 

     return _strings; 
    } 
} 
+0

Die '_strings', die statisch sind, machen dies nicht threadsicher. Bessere Initialisierung als Singleton wäre durch 'private statische readonly _strings = neue Liste ()'. – TToni

+0

Ja, natürlich, aber die Frage ist nicht, "wie besserer Code zu implementieren ist", sondern "warum, wenn ich die Liste auf dem Getter initialisiere, funktioniert es nicht". – Gusman

+0

Aber stellen Sie sich vor, Ihre Antwort erleuchtet Tausende von Entwicklern, die alle Ihren Code in genau diesem Fall verwenden und dann komische, schwer reproduzierbare Effekte und Fehler in ihren gleichzeitigen Webanwendungen bemerken ;-) – TToni

1

Da List<int> auf den Konstruktor der Klasse initialisiert, wo als List<string> nicht der Fall ist. Versuchen Sie:

public MyClass() 
{ 
     _ints = new List<int>(); 
     _strings=new List<string>(); 
} 
0

Ihre '_strings' Liste immer null. Wenn Sie die Eigenschaft 'Strings' 'get' aufrufen, erstellen Sie immer eine neue Listeninstanz und geben sie zurück.

get 
    { 
     // if '_strings' is null, then create new instance of list 
     return _strings ?? new List<string>(); 
    } 

Sie müssen diese verwenden:

get 
    {   
     // If '_strings' is null, then create new instance of list and assign new instance to '_strings' 
     return _strings ?? (_strings = new List<string>()); 
    } 
0

Inline-Variante von Gusman Antwort,

public List<string> Strings => _strings ?? (_strings = new List<string>()); 
-1

An einige der netten Features von C# 6.0 mit FYI, um das Problem vollständig zu verstehen, die Sie auf dieser Linie setzt einen Haltepunkt haben könnten:

return _strings ?? new List<string>(); 

Sie würden _strings gesehen haben, ist immer null und müssen Sie es initialisieren, wie Antworten, die Sie oben so sagen :)

+0

Dies ist keine Antwort, sondern ein Kommentar. – Gusman

+0

@Gusman Ich brauche 50 Ruf für einen Kommentar, und da ich ihm helfen wollte .. musste ich eine Antwort hinterlassen. Nächstes Mal sollte ich nicht einmal versuchen, einem Typen zu helfen? Danke für den Downvote -.- – Emir

+0

Froh, dass es dir gefallen hat. Lesen Sie die Buchungsregeln, bevor Sie sich beschweren, Kommentare als Antworten sind auf S.O. – Gusman

Verwandte Themen