2012-05-02 7 views
6

異種コレクションのための型付きルックアップヘルパー関数が必要です。構造体またはクラスを返す必要があります。アイテムが見つからない場合はnullを返します。 以下は、些細なコレクション検索を使用した例ですが、データベース呼び出しなどであってもかまいません。クラスまたはnullable構造体を返すことができるジェネリックコレクション検索メソッドを実装する方法?

単一のメソッドシグネチャでこれを達成する方法はありますか?私はすでに試した何

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; 
    } 

は:

  • 私は、一般的な制限がオーバーロードを明確にするために使用することができないことを理解しています。だから私は単にこれらの2つのメソッドに同じ名前を付けることはできません。
  • (Default) Tを返すことは、0は有効なint値であるため、オプションではありません。
  • タイプとして<int ?>を呼び出してみましたが、説明したようにNullable<T>は参照型ではありません。

ボックス化されたintを返すように指示する方法はありますか?

答えて

3

次のメソッドは、クラスやNULL可能構造の両方のために働く:

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); 
} 

使用法:?は、ジェネリック型引数の一部であり、上の方法で定義されていないか

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

をお知らせ戻り値の型

+3

I半分このような - しかし、あなたは 'のGetClass 'としてそれを呼び出すと、「0を返すように*それは*ことができます値0で見つけられ、見分けがつかない。実際には、サンプルの使用方法で2番目の '? 'を間違って紛失し、かなり微妙なバグが発生する可能性があります。 ( 'result1'は決してnullにはなりませんが、あなたはそれが期待されます) –

+0

私はintのデフォルトと思いますか? is null – akatakritos

+0

しかし、あなたが探している値が通常のintの場合:私は(oはint?)bc intに失敗すると思いますか? intではありません。 – akatakritos

6

単一のメソッドシグネチャでこれを達成する方法はありますか?

オプションパラメータを使用してコールすると、どちらの場合でも呼び出しコードが同じに見えるように、horrible(本当にひどい)方法があります。しかし、それは不気味です。

オプション:

  • 戻りTuple<T, bool>代わりに
  • NULLかどうかを使用しては存在しないことをシグナリングすることによって、そのoutパラメータ(等int.TryParseなど)
  • 使用する異なるメソッド名

注使用します別の値の場合は、nullを有効な「見つかった」結果にすることができます。この結果はときどき役立ちます。またはは返されないことを保証したいと思っています。

本当に無効にしたい場合は、最後のオプションを使用します。私はそれがあなたのコードをとにかく明確にすると信じています。 IMOは、メソッドが実際にのみ使用する必要があります正確に同じものが別のパラメータを使用して表現されている - 一方で戻り値の型としてNullable<T>を返し、もう1つのケースで戻り値の型としてTを実際に見ることはできません方法。

1

これはあなたが必要とするものとまったく同じです。要求された型がNULL可能型である場合、キャストする前に基礎となる型をチェックします。

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); 
} 

私のテストコード:

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"))); 

結果:

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

'(オブジェクト)42はintですか? 'がtrueです。 '|| 'の必要はありません。 Nullable ... 'チェック。 – dtb

+0

それは、時々私はnullableの周りのコンパイラの魔法が嫌い。 'であるため、他の構造体はtrueを返しません。 –

関連する問題