web-dev-qa-db-ja.com

型が構造体かクラスかをプログラムで確認する方法は?

型が構造体かクラスかをプログラムで確認する方法は?

44
Jader Dias

使用する - Type.IsValueType

Typeが値型かどうかを示す値を取得します。

次のように使用します。

typeof(Foo).IsValueType

または次のような実行時:

fooInstance.GetType().IsValueType

逆に Type.IsClass プロパティ(私の意見ではIsReferenceTypeと呼ばれるべきでしたが、問題ではありません)。これは、テスト対象に基づいて、用途に適している場合とそうでない場合があります。

コードは常にブール否定なしで読みやすくなるので、コードの読みやすさに役立つ方を使用します。


Stefanが以下で指摘するように、構造体を正しく識別するためには、enumsに関して誤検知を回避するように注意する必要があります。 enumは値のタイプであるため、IsValueTypeプロパティはtrueおよびenumsに対してstructsを返します。

したがって、一般的に値型だけでなくstructsを本当に探している場合は、次のようにする必要があります。

Type fooType = fooInstance.GetType();
Boolean isStruct = fooType.IsValueType && !fooType.IsEnum;
74
Andrew Hare
Type type = typeof(Foo);

bool isStruct = type.IsValueType && !type.IsPrimitive;
bool isClass = type.IsClass;

それでも、プリミティブ型またはインターフェースである可能性があります。


編集:構造体の定義については多くの議論があります。構造体と値の型は実際には同じなので、IsValueTypeが正解です。私は通常、型がユーザー定義のstructであるかどうかを知る必要がありました。これは、プリミティブ型ではなく、キーワードstructを使用して実装される型を意味します。だから私と同じ問題を抱えているすべての人のために私の答えを保ちます。


編集2C#リファレンス によると、列挙型は構造体ではありませんが、他の値型は構造体です。したがって、型が構造体であるかどうかを判断する正しい答えは次のとおりです。

bool isStruct = type.IsValueType && !type.IsEnum;

私見、構造体の定義は論理的であるよりも混乱します。私は実際に、この定義が実践において何らかの関連があるとは疑っています。

28

拡張メソッド。これは、コードでtrueとして定義されているものに対してはstructを返しますが、技術的に構造体ではありますが、intのようなものに対しては返しません。

型に子フィールドまたはプロパティが含まれている可能性があるが、structではなくclassとして定義されていることを知る必要がありました。 structを変更すると、コピーが変更されるだけなので、変更を「固定」するには、元のファイルを変更されたコピーに戻す必要があります。

public static bool IsStruct(this Type source) 
{
  return source.IsValueType && !source.IsPrimitive && !source.IsEnum;
}
5
toddmo

以下をお試しください

bool IsStruct(Type t) {
  return t.IsValueType;
}
1
JaredPar

すべての値タイプについて、System.ValueTypeから派生する対応する自動生成クラスタイプがあり、これはSystem.Objectから派生します。値タイプ自体は何からも派生しないことに注意してください。 暗黙的に変換可能 そのクラス型に変換され、そのクラス型のインスタンスは明示的に値型に変換されます。

検討してください:

 public static int GetSomething <T>(T enumerator)where T:IEnumerator <int> 
 {
 T enumerator2 = enumerator; 
 enumerator.MoveNext(); 
 enumerator2.MoveNext(); 
 return enumerator2.Current; 
} 

List<int>.Enumerator型の変数でこのルーチンを呼び出すと、IEnumerator<int>型の変数で呼び出すと、List<int>.Enumeratorのインスタンスが格納されている場合とはまったく異なる動作になります。 List<int>.Enumerator型の変数は値型ですが、List<int>.Enumerator型の変数に格納されているIEnumerator<int>のインスタンスは、クラス型として動作します。

0
supercat