2017-01-05 18 views
0

私はこれやろうとしている:なぜtypeof(int).ToString()は定数ではありませんか?

const string intType = typeof(int).ToString(); 
switch (typeof(MyT).ToString()) 
{ 
    case intType: 
    { 
     return "int"; 
     break; 
    } 
    ... 
} 

をしかし、コンパイラは言う:

エラーCS0133:私が知っているように 'INTTYPE' に割り当てられている表現が

一定でなければならないが、typeofオペレータはコンパイル時に動作します。だから何が問題なの?

+5

'のToString()'、実行時に呼び出されるメソッドです。 –

+2

'typeof(int)'でさえ、const値を返しません。メソッドは、const戻り値を保証しません。 –

+0

'const'の代わりに' readonly'を使い、 'string'の代わりに' Type'を使ってみてください。 –

答えて

11

私が知っているように、typeof演算子はコンパイル時に機能します。

あなたはがあるため知識なければならないことを知りません。 typeofがコンパイル時に実行されるというアイデアはどこにありましたか?定数でないオブジェクトが生成されます。そして、ToStringが実行されるたびに異なる文字列を生成しないという保証はないので、定数として扱うこともできません。

どうしたのですか?

あなたは誤った信念から推論しています。

C#仕様では、式をコンパイル時定数にするために満たす必要がある条件を明確に示しています。これらの条件には、演算子またはメソッド呼び出しを含まない式が含まれます。

しかし、ここでははるかに大きな問題があります。私はMyTがジェネリック型パラメータであると仮定します。つまり、ジェネリック型パラメータの値をオンにしようとしています。それはほとんど常に間違ったことです。

あなたは本当に何をしようとしていますか?あなたは本当に解決しようとしている問題は何ですか?これまでに示したこのコードは、実際の問題が何であれ解決するための非生産的な道を辿ることを示しているからです。

+0

はい、@ user1234567 - あなたは本当に何をしようとしていますか? –

+0

@エリック、私の不正確な点で申し訳ありません。答えに感謝します。私はC#の初心者です。そして、私が「知っている」と言っていた 'typeof'に関する私の絵は、相対的な質問に対するいくつかの回答の表面的なレビューに依存しています。そして、 'typeof'は' GetType'(実行時の型を与える)とは対照的に、コンパイル時の型を与えているようです。したがって、コンパイル時の型の実行時取り出しを延期する理由はありません。 – user1234567

+4

@ user1234567:ああ、私はあなたの混乱の源を今見ています。明確化のためにありがとう。はい、 'GetType'は、オブジェクトのランタイム*に知られている型*を返します。また、' typeof'はそのオペランドとしてコンパイラ*型に知られています。しかし、これは、演算がコンパイル時に*実行されることを意味するものではありません。これは、式を定数にするために必要なことです。 'typeof'式は' Type'型のオブジェクトを生成します。これは実行時オブジェクトです。 –

1

私は、それは彼が達成したいものを、非常に明白だと思う:

彼はswitch-caseに代わりのif-elseif経由型の等価性をチェックしたいです。正直言って、どうして?しかし、どのようにこれを達成することができますか?

  1. 最初のオプション:C# 7.0を待ちます。そうですね、これは将来可能ですね!

  2. 2番目のオプション:文字列を使用します。しかし、caseの文字列は一定である必要があります。だから、素晴らしいのはどうですか?nameof

私はちょうどこの「美しさ」を試してみました、それが動作しますので、多分これはあなたの問題を解決:

switch (typeof(Int32).Name) 
{ 
    case nameof(Int32): 
     Console.WriteLine("It's an Int32!"); 
     break; 
    case nameof(Double): 
     Console.WriteLine("It's a Double"); 
     break; 
} 
+1

これは 'nameof'の使い方ですが、ここでも大きな問題があると思います。もしあなたがタイプスイッチ*をしているとすれば、何かが間違っている可能性があります。タイプを切り替えるよりも、問題を解決するほうがずっと良い方法があります。 –

+4

また、あなたのソリューションでは、型が名前空間で修飾されていないと仮定しています。たとえば、case nameof(Foo.Bar):... case nameof(Blah.Bar): '' Bar ''なので、あなたはインスタンス名を持つことができませんでした。 –

+0

もちろん、そうです。私は知っています、これは単なる回避策であり、__real__型の比較が必要かどうかを常に確認する必要があります。幸いにも、C#7.0では、この回避策は必要ありません。 –

2

既知の種類のタイプMyTを比較するための唯一の方法は、平等のために彼らのTypeオブジェクトを確認することです。これは以下のように行うことができます。

if (typeof(MyT) == typeof(int)) return "int"; 
if (typeof(MyT) == typeof(decimal)) return "decimal"; 
// etc... 

あなたは(現時点では)のでswitchにこのアプローチを使用することはできませんswitchチェックされているアイテムは、シンプルなタイプであることが必要です。

switch (typeof(T)) // Compile error: "switch expression or case label must be a bool, 
        // char, string, integral, enum, or corresponding nullable type" 
{ 
    case typeof(int): return "int"; 
    case typeof(decimal): return "decimal"; 
    // ... 
} 

もすでに述べたように、このように型をチェックすることは、ほとんどの場合、異なるオブジェクト指向の原則を適用することによって、あなたのアプローチを改善できることを意味します。

など。代わりにMyTの型チェックとMyMethod<MyT>(MyT item)MyMethod(int item)を行うことを検討、MyMethod(decimal item)などの

-1

あなただけのオブジェクトの型を表す文字列を取得しようとしている場合は、あなただけの代わりに)(.GetTypeを呼び出す必要があります。

たとえば、以下は、オブジェクト型の文字列名を返す小さな関数です。

static string GetTypeString(object obj) 
{ 
     return obj.GetType().FullName; 
} 

これはオブジェクトへのフルパスに戻ります。 intの場合、System.Int32を返します。 Int32の部分だけが必要な場合は、代わりにGetType()。Nameを使用します。

また、中断する必要はありません。あなたがリターンを持っているならばスイッチで。

特定のコード、または返す特定の文字列に対して実行する必要がある特定のコードがある場合は、上記で返された値に文字列を使用できます。例:

static string GetSimpleType(object obj) 
    { 
     var stringRepresentation = GetTypeString(obj); 
     switch (stringRepresentation) 
     { 
      case "System.Int64": 
      case "System.Int32": 
       return "int"; 

      default: 
       return stringRepresentation; 
     } 
    } 

デフォルトは、大文字と小文字を区別しないすべてのスイッチステートメントでキャッチされます。それは他人のように考えてください。

上記の例では、int、Int32、およびInt64に同じ値を返します。ケースラベルが空の場合、ケースラベルは他のケースラベルに落ちる可能性があります。

単純なスクリプトを実行して文字列の値をハードコードすることで、スイッチを作成するために必要なすべての値を見つけることができます。これらの値は常に同じ型のため同じです。文字列が異なる場合、型は異なります。

あなたはタイプを比較している場合は最後に、場合とそうでない場合は、より良い作品:

 static string GetSimpleType(object obj) 
     { 
      if (obj.GetType() == typeof(int)) 
      { 
       return "int"; 
      } 

      return obj.GetType().ToString(); 
     } 
関連する問題