2015-09-15 16 views
21

angewendet werden Der Versuch Feature generic und dann plötzlich sagte CompilerOperator '?' kann nicht auf Operanden vom Typ ‚T‘

Operator zu machen ‚?‘ kann nicht auf Operanden vom Typ ‚T‘

hier angewendet werden, ist der Code

public abstract class Feature<T> 
{ 
    public T Value 
    { 
     get { return GetValue?.Invoke(); } // here is error 
     set { SetValue?.Invoke(value); } 
    } 

    public Func<T> GetValue { get; set; } 
    public Action<T> SetValue { get; set; } 
} 

Es ist möglich, diesen Code zu verwenden, anstatt

get 
{ 
    if (GetValue != null) 
     return GetValue(); 
    return default(T); 
} 

Aber ich frage mich, wie sie zu beheben das schöne C# 6.0 One-Liner.

+1

Das ist wirklich interessant. Ich denke, es könnte ein Fehler sein. Alle Antworten, die 'schlagen vor, mit denen T: CLASS' der Tatsache fehlt, dass Sie nicht ein' T', als zweiten Codeblock zeigt null, wenn der 'Func ' sind Kontrolle ist. Wenn das funktioniert, dann sollte die 'GetValue? .Invoke()' Syntax auch funktionieren. Sie sollten in der Lage sein zu schreiben: 'return GetValue? .Invoke() ?? default (T) ' – kjbartel

+0

@kjbartel: Ich glaube, es liegt daran, dass'? .' 'null' zurückgibt, wenn der Ausdruck' null' ist und nicht 'default (T)'. – Joey

+1

Func ist nullfähig. – kjbartel

Antwort

26

Da nicht alles null sein kann, eine Referenz-Typ oder ein Nullable-Typ sein muss, müssen Sie T verengen etwas nullable (auch bekannt als ein object) zu sein. Structs können nicht null sein und auch keine Enums.

Hinzufügen eines where auf class das Problem nicht beheben:

public abstract class Feature<T> where T : class 

Also warum es nicht nur Arbeit?

Invoke()T ergibt. Wenn GetValuenull ist, setzen die ? Bediener den Rückgabewert vom Typ T zu null, die es nicht können. Wenn Tint zum Beispiel ist, kann es nicht machen es nullable (int?), da der tatsächliche Typ erforderlich (T = int) nicht. Wenn Sie in Ihrem Code T zu int ändern, werden Sie das Problem sehr deutlich sehen. Das Endergebnis, was Sie fragen, ist dies:

get 
{ 
    int? x = GetValue?.Invoke(); 
    return x.GetValueOrDefault(0); 
} 

Dies ist nicht etwas, das Null-Ausbreitungs Operator für Sie tun. Wenn Sie auf die Verwendung von zurückgreifen, weiß es genau, was zu tun ist, und Sie vermeiden die "problematische" Null-Propagierung.

+0

Das Hinzufügen der 'T: class'-Klausel führt zu einem anderen Problem, soll ich eine andere Frage stellen oder ist es einfach? Ich habe 'öffentliche Klasse FeatureBool: Feature {}' und es sagt jetzt * "Der Typ 'T' muss ein Referenztyp sein, um es als Parameter 'T' im generischen Typ oder Methode 'Feature '" * . Ich bin mir nicht sicher, ob es eine bessere Wahl als "class" gibt (ich kann 'object' nicht verwenden) oder sollte ich etwas mit' FeatureBool' selbst machen? – Sinatr

+4

Ich würde nur akzeptieren, dass der C# -Compiler dies nicht erlaubt und dass Sie Ihre Option # 2 benötigen, um diese Arbeit zu machen. Nicht alles muss ein Liner sein, oder? –

+1

Der tatsächliche Fehler ist 'Kann den bedingten Zugriffsausdruckstyp 'T' nicht auf NULL-Typ heben. Der Operator ".?" Umschließt den Rückgabetyp des untergeordneten Elements in "Nullable <>". Der Compiler kann 'Nullable ', aber nicht 'Nullable ' verarbeiten. Deshalb gibt es keinen Fehler für "Aktion .Invozieren". –

4

Soweit ich weiß, dass der ?. Operator fest einprogrammiert ist mit null zu arbeiten, das heißt, es funktioniert für Referenztypen oder Nullable-Wertetypen, aber nicht normale Werttypen. Das Problem ist wahrscheinlich, dass der Operator gibt null, wenn der Ausdruck null statt default(T) ist.

Sie könnten in der Lage sein, es zu beheben, indem T-class hier zu beschränken.

+0

@PanagiotisKanavos: 'Nullable ' wird vom Compiler als nullable behandelt, wie es sollte, aber [es ist ein Werttyp] (http://referencesource.microsoft.com/#mscorlib/system/nullable.cs,ffebe438fd9cbf0e). – Joey

+0

sollte die Referenzquelle zuerst überprüft haben! –

8

T

public abstract class Feature<T> where T : class 
{ 
    // ... 
} 
Verwandte Themen