2008-08-28 11 views
78

私は任意の型、プリミティブなどを許可する汎用クラスを持っています。これの唯一の問題はdefault(T)を使用していることです。値型または文字列でdefaultを呼び出すと、それは妥当な値(空の文字列など)に初期化されます。オブジェクトに対してdefault(T)を呼び出すと、nullが返されます。いろいろな理由から、プリミティブ型でない場合は、ではないの型のデフォルトインスタンスが存在することを保証する必要があります。ここでの試み1:ジェネリック型が文字列かどうかをテストする最良の方法? (C#)

T createDefault() 
{ 
    if(typeof(T).IsValueType) 
    { 
     return default(T); 
    } 
    else 
    { 
     return Activator.CreateInstance<T>(); 
    } 
} 

問題 - 文字列が値型ではありませんが、パラメータなしのコンストラクタを持っていません。したがって、現在の解決策は次のとおりです。

T createDefault() 
{ 
    if(typeof(T).IsValueType || typeof(T).FullName == "System.String") 
    { 
     return default(T); 
    } 
    else 
    { 
     return Activator.CreateInstance<T>(); 
    } 
} 

しかし、これはクルージュのように感じます。文字列の場合を処理するためのより良い方法はありますか?

答えて

133

デフォルト(文字列)はstring.Emptyではなくnullであることに注意してください。あなたのコード内の特殊なケースをしたいことがあります。

if (typeof(T) == typeof(String)) return (T)(object)String.Empty; 
+2

私は以前その解決策を試したと思ったし、それが動作しませんでした、しかし、私は何か愚かなことをしたに違いない。そして、デフォルト(文字列)がnullを返すことを指摘してくれてありがとうございました。私たちはそれによってまだエラーに陥っていませんでしたが、それは本当です。 –

+1

@Matt Hamilton:+1ですが、メソッドの戻り値の型が汎用的であるため、CodeInChaosが提案したように '(T)(object)String.Empty'を返すように答えを更新する必要があります。 – VoodooChild

+2

'is'キーワードはどうですか?ここで使うのではないですか? –

13
if (typeof(T).IsValueType || typeof(T) == typeof(String)) 
{ 
    return default(T); 
} 
else 
{ 
    return Activator.CreateInstance<T>(); 
} 

未検証ですが、最初に心に浮かんだことがあります。

4

あなたはTypeCode列挙体を使用することができます。 IConvertibleインターフェイスを実装するクラスのGetTypeCodeメソッドを呼び出して、そのクラスのインスタンスの型コードを取得します。 IConvertibleはBoolean、SByte、Byte、Int16、UInt16、Int32、UInt32、Int64、UInt64、Single、Double、Decimal、DateTime、Char、およびStringで実装されているため、これを使用してプリミティブ型をチェックできます。 "Generic Type Checking"の詳細

-6

Stringの説明はここでは機能しません。

私はそれを動作させるためにジェネリック医薬品のためのコードを、以下の必要がありました -

個人的に
private T createDefault() 
    { 

     {  
      if(typeof(T).IsValueType)  
      {   
       return default(T);  
      } 
      else if (typeof(T).Name == "String") 
      { 
       return (T)Convert.ChangeType(String.Empty,typeof(T)); 
      } 
      else 
      { 
       return Activator.CreateInstance<T>(); 
      } 
     } 

    } 
+3

名前空間ではなく、特に名前空間に関係なく「文字列」をテストするのは悪いです。そして私はあなたがどちらかに変換する方法が嫌いです。 – CodesInChaos

+0

-1これは正しいイコライジングではありません – IamStalker

2

を、私は、メソッドのオーバーロードが好き:

public static class Extensions { 
    public static String Blank(this String me) {  
    return String.Empty; 
    } 
    public static T Blank<T>(this T me) {  
    var tot = typeof(T); 
    return tot.IsValueType 
     ? default(T) 
     : (T)Activator.CreateInstance(tot) 
     ; 
    } 
} 
class Program { 
    static void Main(string[] args) { 
    Object o = null; 
    String s = null; 
    int i = 6; 
    Console.WriteLine(o.Blank()); //"System.Object" 
    Console.WriteLine(s.Blank()); //"" 
    Console.WriteLine(i.Blank()); //"0" 
    Console.ReadKey(); 
    } 
} 
関連する問題