2012-10-30 72 views
8

假設我有以下類:瞭解C#泛型和Nullable值類型。返回null或爲空的

public class GenericClass<T> 
{ 
    public T Find() 
    { 
     //return T if found otherwise null or Nullable<T> 
    } 
} 

某處,我想專門使用T我班有class,其他時間用struct。 我正要面對這個issue:如果T類型不限於struct,我不能返回Nullable<T>

我想提供我Find方法的實現,如果T專業同時具有classstruct的作品。 如果Find失敗,我想返回null如果T是一類,否則Nullable<T>

這可能沒有使用反射?如果是的話如何?

+0

您不能返回T或可空如果返回類型是T – fsimonazzi

回答

15

您可以返回default(T)

對於一個班級,這將是null。對於任何Nullable<T>,這將是一個沒有值的Nullable<T>(實際上是null)。

這就是說,如果你使用struct而不是Nullable<T>作爲類型,default(T)將是該結構的默認值。


如果你想使這項工作統一進行任何類或結構,你可能會需要返回兩個值 - 你可以在這裏使用的框架爲靈感,並有TryXXX方法,即:

public bool TryFind(out T) 

如果未找到該值,則可以使用default(T)並返回false。這避免了對可空類型的需要。你也可以寫這個返回Tuple<bool, T>或類似的,如果你想避免出參數,即:

public Tuple<bool, T> Find() 

最後一個選擇,可能,將是使你的類非通用的,然後使用一對泛型方法:

class YourClass // Non generic 
{ 
    public T FindReference<T>() where T : class 
    { 
     // ... 
     return null; 
    } 

    public Nullable<T> FindValue<T>() where T : struct 
    { 
     // ... 
     return default(T); 
    } 
} 

請注意,你需要不同的名稱,因爲你不能有一個重載的方法完全基於返回類型。

+0

從技術上說,'默認(T)'不會返回一個'可空'當作爲OP所需的泛型參數提供了「int」,但這絕對能讓你獲得大部分的途徑。確實,獲得OP所需要的唯一方法是提供兩個通用實現,一個用於值類型,另一個用於參考類型。 – Tejs

+0

@Tejs。所以如果我需要使用數字類型專門化T,我是否被迫使用out參數來實現通用解決方案?如果T是一個int,默認返回什麼? – Heisenbug

+0

@Tejs是的 - 這就是我想說的最後一句話 - 如果您使用'Nullable '作爲泛型類型,則'default(T)'將提供'Nullable '。 –

2

我會採用如下方案:

public Boolean Find(out T result) 
{ 
    // Pseudo code 
    if (FindItem == true) 
    { 
     result = ItemFound; 
     return true; 
    } 
    result = default(T); 
    return false; 
} 

爲什麼?因爲Nullable<T>只接受一個結構,上面的方法支持類和結構。

+1

+1,這個習慣用法通常命名爲「TryXXXX」,所以'TryGetValue'或'TryFind'將會是合適的。 – user7116

+0

@sixlettervariables是的,你是對的。但我留下了海森堡使用的名字。 –

0

由於裏德說你可以返回default(T)

在我看來,這有一個很大的缺點:如果你的方法指出default(T)是返回的,如果沒有找到該項目,你失去了返回值類型的默認值的能力。返回0對於Find<int>可能通常是完全有效的返回值)。

我寧願去這樣的事情

public class GenericClass<T> 
{ 
    public Option<T> Find() 
    { 
     //return Option.Some(item) if found otherwise Option.None<T>() 
    } 
} 

public static class Option 
{ 
    public static Option<T> None<T>() 
    { 
     return new Option<T>(default(T), false); 
    } 

    public static Option<T> Some<T>(T value) 
    { 
     return new Option<T>(value, true); 
    } 
} 

public sealed class Option<T> 
{ 
    private readonly T m_Value; 
    private readonly bool m_HasValue; 

    public void Option(T value, bool hasValue) 
    { 
     m_Value = value; 
     m_HasValue = hasValue; 
    } 

    public bool HasValue 
    { 
     get { return m_HasValue; } 
    }   

    public T Value 
    { 
     get { return m_Value; } 
    } 
} 
+1

這實際上是寫了一種不受結構限制的'Nullable '的新形式 - 現在,如果C#有模式匹配,這將是要走的路;) –