1. ホーム
  2. c#

ある型が「単純」型かどうかを判断するには?

2023-10-23 06:18:16

質問

typeof(string).IsPrimitive == false
typeof(int).IsPrimitive == true
typeof(MyClass).IsClass == true
typeof(string).IsClass == true
typeof(string).IsByRef == false
typeof(MyClass).IsByRef == true // correction: should be false (see comments below)

T の新しいインスタンスをインスタンス化し、それが "complex" クラスである場合、ソースデータの値のセットからそのプロパティを埋めるメソッドがあります。

(a) Tが単純な型(例えば文字列やintやその他類似のもの)である場合、ソースデータからTへの迅速な変換が実行されることになっています。

(b) Tがクラス(ただし、文字列のような単純なものではない)である場合、Activator.CreateInstanceを使用して、フィールドに入力するために少し反射を行うつもりです。

メソッド(a)またはメソッド(b)を使用すべきかどうかを判断する迅速で簡単な方法はありますか?このロジックは、Tを型引数として持つジェネリックメソッドの内部で使用される予定です。

どのように解決するのですか?

文字列は特殊なケースだと思われます。

私ならそうすると思います...。

bool IsSimple(Type type)
{
    return type.IsPrimitive 
      || type.Equals(typeof(string));
}


編集してください。

時には、列挙型や小数のような、さらにいくつかのケースをカバーする必要があります。列挙型はC#では特別な種類の型です。小数は他のものと同じように構造体です。構造体の問題は、構造体が複雑であったり、ユーザー定義型であったり、単なる数値であったりすることです。だから、区別するためには、それらを知ること以外にチャンスはないのです。

bool IsSimple(Type type)
{
  return type.IsPrimitive 
    || type.IsEnum
    || type.Equals(typeof(string))
    || type.Equals(typeof(decimal));
}

nullableの相手方の処理もちょっと厄介です。nullable自体は構造体です。

bool IsSimple(Type type)
{
  if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
  {
    // nullable type, check if the nested type is simple.
    return IsSimple(type.GetGenericArguments()[0]);
  }
  return type.IsPrimitive 
    || type.IsEnum
    || type.Equals(typeof(string))
    || type.Equals(typeof(decimal));
}

テストします。

Assert.IsTrue(IsSimple(typeof(string)));
Assert.IsTrue(IsSimple(typeof(int)));
Assert.IsTrue(IsSimple(typeof(decimal)));
Assert.IsTrue(IsSimple(typeof(float)));
Assert.IsTrue(IsSimple(typeof(StringComparison)));  // enum
Assert.IsTrue(IsSimple(typeof(int?)));
Assert.IsTrue(IsSimple(typeof(decimal?)));
Assert.IsTrue(IsSimple(typeof(StringComparison?)));
Assert.IsFalse(IsSimple(typeof(object)));
Assert.IsFalse(IsSimple(typeof(Point)));  // struct in System.Drawing
Assert.IsFalse(IsSimple(typeof(Point?)));
Assert.IsFalse(IsSimple(typeof(StringBuilder))); // reference type

.NET Coreに関する注意事項

でDucoJが指摘しているように の回答で指摘しています。 のように、使用されているメソッドのいくつかは、クラスで使用できません。 Type のクラスではもう利用できません。

修正したコード(うまくいくといいのですが、自分では試せませんでした。 そうでない場合はコメントください)。

bool IsSimple(Type type)
{
  var typeInfo = type.GetTypeInfo();
  if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>))
  {
    // nullable type, check if the nested type is simple.
    return IsSimple(typeInfo.GetGenericArguments()[0]);
  }
  return typeInfo.IsPrimitive 
    || typeInfo.IsEnum
    || type.Equals(typeof(string))
    || type.Equals(typeof(decimal));
}