2012-05-02 9 views
6

Heterojen bir koleksiyon için yazılan bir arama yardımcı işlevi istiyorum: Bir öğe veya sınıf döndürmeli, yoksa öğe bulunamazsa null. Aşağıda önemsiz bir koleksiyon arama kullanarak bir örnek, ancak bir veritabanı çağrısı veya her ne olabilir.Sınıf veya null yapıya dönebilen genel koleksiyon arama yöntemi nasıl uygulanır?

Bunu tek bir yöntem imzasıyla gerçekleştirmenin herhangi bir yolu var mı? Daha önce de denedim ne

public T GetClass<T>(string key) where T : class 
    { 
     object o; 
     if (Contents.TryGetValue(key, out o)) 
     { 
      return o as T; 
     } 
     return null; 
    } 

    public T? GetStruct<T>(string key) where T : struct 
    { 
     object o; 
     if (Contents.TryGetValue(key, out o)) 
     { 
      if (o is T) 
      { 
       return (T?) o; 
      } 
     } 
     return null; 
    } 

:

  • Ben jenerik kısıtlamalar aşırı yükleri belirginleştirmek için kullanılan edilemez anlıyoruz. Bu yüzden bu iki yönteme aynı ismi veremem.
  • (Default) T döndürme bir seçenek değildir, çünkü 0 geçerli bir int değerdir.
  • Tür olarak <int ?> numaralı telefonu arayarak denedim, ancak tartışıldığı gibi, Nullable<T> bir başvuru türü değil.

Kutulu bir ürünü iade edeceğimi belirtmenin bir yolu var mı?

cevap

3

şu yöntem sınıfları ve null yapıları hem de çalışır:

public static T GetValue<T>(string key) 
{ 
    object o; 
    if (Contents.TryGetValue(key, out o)) 
    { 
     if (o is T) 
     { 
      return (T)o; 
     } 
    } 
    return default(T); 
} 

Kullanımı: ? üzerine yöntemiyle belirlenen genel tür tartışmanın parçası olmaması nasıl

int? result1 = GetValue<int?>("someInt"); 
string result2 = GetValue<string>("someString"); 

Bildirimi dönüş tipi.

+3

Yarım böyle - ama "' getClass 'olarak diyoruz ve 0 verilecek * o * tanır 0 "ve" bulunamadı "değerleriyle birlikte bulundu. Gerçekten de, örnek kullanımınızda ikinci '' 'hatalarını kaçırıp oldukça ince bir hata elde edebilirsiniz. ('sonuç1' * asla * boş olamaz, ama olmasını beklersiniz) –

+0

Int için varsayılanı düşünüyorum? null – akatakritos

+0

Ama ne aradığınız değer düzenli bir int ise: b (o int?) bc int başarısız olacağını düşünüyorum? int değil – akatakritos

6

Bunu tek bir yöntem imzasıyla gerçekleştirmenin herhangi bir yolu var mı?

çağıran kodu her iki durumda da aynı görünüm böylece isteğe bağlı parametreleri kullanarak bunu yapmak için horrible (gerçekten iğrenç) yolu var. Yine de çok saçma.

Seçenek:

  • geri Tuple<T, bool> yerine
  • Kullanıcıyı bir out parametre (gibi int.TryParse vs.)
  • Kullanımı farklı yöntem adları

Not Geçersizlik kullanarak bu yokluğunun sinyal ile Bir değer ayrı ayrı, null geçerli bir "bulundu" sonucu, bazen yararlı olabilir yapabilirsiniz. Veya , numaralı telefonun size asla iade edilmeyeceğini garanti etmek isteyebilirsiniz.

Gerçekten boşluğu kullanmak istiyorsanız, son seçenek için giderdim. Kodunuzu yine de temizleyeceğine inanıyorum. IMO, aşırı yükleme gerçekten sadece yöntemler tam farklı parametreler kullanılarak ifade edilen aynı şeyi yaparken kullanılmalıdır - bir durumda dönüş tipi olarak Nullable<T> döndürme ve diğer durumda dönüş türü olarak T gerçekten görülemez yol.

1

Bu tam olarak bunu gerekenleri yapmalıdır. İstenen tür null bir türse, dökümden önce alttaki türü kontrol edin.

public static T GetValue<T>(string key) 
{ 
    object o; 
    if (Contents.TryGetValue(key, out o)) 
    { 
     if (o is T || Nullable.GetUnderlyingType(typeof(T)) == o.GetType()) 
     { 
      return (T)o; 
     } 
    } 

    return default(T); 
} 

Testim kodu:

Contents.Add("a string", "string value"); 
Contents.Add("an integer", 1); 
Contents.Add("a nullable integer", new Nullable<int>(2)); 

// Get objects as the type we originally used. 
Debug.WriteLine(string.Format("GetValue<string>(\"a string\") = {0}", GetValue<string>("a string"))); 
Debug.WriteLine(string.Format("GetValue<int>(\"an integer\") = {0}", GetValue<int>("an integer"))); 
Debug.WriteLine(string.Format("GetValue<int?>(\"a nullable integer\") = {0}", GetValue<int?>("a nullable integer"))); 

// Get objects as base class object. 
Debug.WriteLine(string.Format("GetValue<object>(\"a string\") = {0}", GetValue<object>("a string"))); 
Debug.WriteLine(string.Format("GetValue<object>(\"an integer\") = {0}", GetValue<object>("an integer"))); 
Debug.WriteLine(string.Format("GetValue<object>(\"a nullable integer\") = {0}", GetValue<object>("a nullable integer"))); 

// Get the ints as the other type. 
Debug.WriteLine(string.Format("GetValue<int?>(\"an integer\") = {0}", GetValue<int?>("an integer"))); 
Debug.WriteLine(string.Format("GetValue<int>(\"a nullable integer\") = {0}", GetValue<int>("a nullable integer"))); 

// Attempt to get as a struct that it's not, should return default value. 
Debug.WriteLine(string.Format("GetValue<double>(\"a string\") = {0}", GetValue<double>("a string"))); 

// Attempt to get as a nullable struct that it's not, or as a class that it's not, should return null. 
Debug.WriteLine(string.Format("GetValue<double?>(\"a string\") = {0}", GetValue<double?>("a string"))); 
Debug.WriteLine(string.Format("GetValue<StringBuilder>(\"a string\") = {0}", GetValue<StringBuilder>("a string"))); 

Sonuçlar:

GetValue<string>("a string") = string value 
GetValue<int>("an integer") = 1 
GetValue<int?>("a nullable integer") = 2 

GetValue<object>("a string") = string value 
GetValue<object>("an integer") = 1 
GetValue<object>("a nullable integer") = 2 

GetValue<int?>("an integer") = 1 
GetValue<int>("a nullable integer") = 2 

GetValue<double>("a string") = 0 

GetValue<double?>("a string") = 
GetValue<StringBuilder>("a string") = 
+0

'(object) 42 int?' True. '|| için gerek yoktur Nullable ... 'kontrol edin. – dtb

+0

Dang, bazen derleyici büyüsünden null olarak nefret ediyorum. , 'için başka bir yapı doğru olmaz. –

İlgili konular