2010-09-09 42 views
12

übte Generics. Betrachten Sie eine Stapelmethode unten. Was ist die beste Möglichkeit, Fehler zu überprüfen, außer das Auslösen von Ausnahmen in einer generischen Methode? Was, wenn ich ein Ergebnis in dieser Methode zurückgeben möchte.Generic Rückgabetyp in C#

public T pop() 
{ 
    if (top >= 0) 
     return arr[top--]; 
    return -1 or null; 
} 

Antwort

15

Das einzige, was Sie tun können, ist default(T) zurückgeben, was der Standardwert für den Typ ist T (null für Referenztypen null für integrale Typen und genullt-Felder Objekt für andere Werttypen). Dies ist jedoch in der Regel eine schlechte Idee, da Sie keine Möglichkeit haben, zwischen einem 0, der ausgelöst wurde, oder einem 0, der einen Fehler anzeigt, zu unterscheiden. Ausnahmen sind normalerweise der beste Weg, um in solchen Fällen zu gehen, aber Sie könnten auch Ihre Methode wie folgt ändern:

public bool TryPop(out T value) 
{ 
    if (top >= 0) 
    { 
     value = arr[top--]; 
     return true; 
    } 
    value = default(T); 
    return false; 
} 
+0

Thanks All! Benötigte eine Alternative zu Ausnahmen. Wusste nicht über Standard (T). –

+0

Hmmm, eine Funktion, die einen Parameter ändert ... wie unfunktionell (ja, ich benutze TryParse, aber ich versuche, mich von Dingen fernzuhalten, die sich selbst Funktionen nennen, aber nicht wirklich sind). –

+0

@Edgar sehen es nicht als Ändern eines Parameters, sehen Sie es als zweiten Rückgabewert. Es ist nicht schlimmer als die Rückkehr eines 'Tuple '. Wovor Sie Angst haben sind Ref-Parameter. – Trillian

6

Sie könnten tun return default(T), die 0 initialisiert Werttypen (ex. Alle numerischen Typen auf 0 initialisiert wird) zurück, und null für Referenztypen.

+0

+1, sollte ein Bit hinzufügen, dass es 0 initialisierte Werte für alle Strukturtypen zurückgibt (im Wesentlichen die numerischen Typen Teil erweitern) – JaredPar

+0

Dies ist eine schlechte Idee, denn dann können Sie nicht zwischen einem Objekt, dessen Wert abgerufen wurde, unterscheiden 'default (T)' und ein Fehler, der durch die Rückgabe von 'default (T)' signalisiert wird. – Trillian

+0

@JaredPar Wahr, fertig. –

0

Ihre Frage ist unklar. Fehler Überprüfung kann auf die gleiche Weise wie immer erfolgen - Abfangen von Ausnahmen. Fehler Fehler sollten in der Regel durch Auslösen von Ausnahmen durchgeführt werden. Dafür sind sie schließlich da.

Wenn Sie zurück null wollen Sie das tun können, aber dann müssen Sie diese Art stellen Sie sicher, T eine Klasse ist, nicht eine Struktur, etwa so:

public T pop() 
    where T: class 
{ 
    ... 
} 
1

Es ist wie Ihre Frage scheint wirklich hat zwei Teile

Der erste Teil ist, wie man einen Standardwert zur Verfügung stellt, wenn einer nicht verfügbar ist. Wie andere Leute darauf hingewiesen haben, funktioniert der C# -Ausdruck default(T) für dieses Szenario. Es gibt null für Referenztypen und 0 initialisierte Werte für Strukturen zurück.

Der zweite Teil ist, was der beste Weg ist, den Fehlerfall anders als eine Ausnahme zu werfen. Sammlung APIs sind in der Regel die TryXXX Muster für diese Art von Szenario

bool TryPop(out T value) { 
    if (top >= 0) { 
    value = arr[top--]; 
    return true; 
    } 
    value = default(T); 
    return false; 
} 
0

verwenden Wenn Sie in der Lage sein wollen null zurück, wenn der Stapel leer ist, dass Sie so etwas wie dies versuchen:

class GenericStack<T> 
{ 
    T[] arr; 
    int top; 

    public T pop() 
    { 
     if (top >= 0) 
      return arr[top--]; 
     return default(T); 
    } 
} 

Und dann Sie können verwenden wie folgt:

 var stack = new GenericStack<int?>(); 

     var res = stack.pop(); // res will be null 

Beachten Sie, dass das Stack-Objekt vom Typ int ist? so können wir Nullen zurückgeben.

0

Direkt Ansatz (Verwendung Generika und Rückgabewert oder null)

class DemoClass<T> where T : struct 
{ 
    public T? PopValueOrNull() 
    { 
    if (this._top >= 0) { 
     return this._arr[this._top--]; 
     } 

     return null; 
    } 
} 
+0

ok, ich vergesse "wo T: struct" :) ... warte eine Sekunde ... hinzugefügt – Andrey

1

ich auf der Suche nach einer Lösung für eine etwas andere Frage hier kam, eine statische Methode mit, die eine neue generische zwei generische Arrays und gibt nimmt Array. Da meine Methode statisch war, konnte ich das Beispiel nur als Inspiration verwenden. Stattdessen habe ich folgende Lösung entwickelt.

T [ ] raMerged = (T [ ]) alMerged.ToArray (typeof (T)); 
return raMerged; 

Im obigen Snippet ist alMerged eine ArrayList von generischen Objekten T.

Dies erfüllt die Bedingungen des durch die Methodensignatur spezifizierten Vertrags, der wie folgt ist.

public static T [ ] MergeNewItemsIntoArray<T> (
T [ ] paMasterList , 
T [ ] paNewItems) 
where T : IComparable , new () 

In der Signatur, die where-Klausel meine Auflösung einer anderen Ausgabe zeigt, dass ich in mehreren Threads gefunden, von denen keines direkt auf diese Frage gerichtet. Trotzdem wird dies hoffentlich wenigstens einer anderen Seele helfen.