ジェネリック型が文字列かどうかをテストする最良の方法は?(C#)


93

プリミティブなどの任意のタイプを許可するジェネリッククラスがあります。これに関する唯一の問題は、の使用default(T)です。値型または文字列に対してdefaultを呼び出すと、それはそれを適切な値(空の文字列など)に初期化します。default(T)オブジェクトを呼び出すと、nullが返されます。さまざまな理由により、プリミティブ型でない場合は、null ではなく、その型のデフォルトのインスタンスが存在することを確認する必要があります。これが試行1です。

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

しかし、これはクラッジのように感じます。文字列のケースを処理するより良い方法はありますか?

回答:


161

default(string)はnullであり、string.Emptyではないことに注意してください。コードで特別なケースが必要になる場合があります。

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

2
私はその解決策を以前に試したがうまくいかなかったと思ったが、私は愚かなことをしたに違いない。そして、default(string)がnullを返すことを指摘してくれてありがとう、それが原因でまだエラーに遭遇しませんでしたが、それは本当です。
レックスM

1
@Matt Hamilton:+1。ただし、CodeInChaosの提案に従って '(T)(object)String.Empty'を返すように答えを更新する必要があります。メソッドの戻り値の型は汎用なので、単に文字列を返すことはできません。
VoodooChild

2
およそ何isキーワード?ここでの使用ではないですか?
ネイビードバット、2014

現時点では、ジェネリック及び譲渡または直接インスタンス化と事業者であることは?クールな機能になりますではありません適用可能ではない
ファン・パブロ・ガルシア・コエーリョ

14
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によって実装されるため、これを使用してプリミティブ型を確認できます。「ジェネリック型チェック」の詳細。


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


-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
String特に名前空間を考慮せずに名前でテストすることは悪いことです。また、変換方法も好きではありません。
CodesInChaos、2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.