2011-11-17 15 views
58

に型 'のInt' を変換できません。しかし、コンパイルするとき、私は得る:は、暗黙のうちに、私は<code>Get<int>(Stat);</code>または<code>Get<string>(Name);</code></p> <p>を呼び出すことができます 'T'

は、暗黙的に 'T'

に型 'int型' を変換できません。

と同じものです。

public T Get<T>(Stats type) where T : IConvertible 
{ 
    if (typeof(T) == typeof(int)) 
    { 
     int t = Convert.ToInt16(PlayerStats[type]); 
     return t; 
    } 
    if (typeof(T) == typeof(string)) 
    { 
     string t = PlayerStats[type].ToString(); 
     return t; 
    } 
} 
+4

あなたはおそらく、もしブロックはブロック内で、あなたはTがintである知っている、あなたが暗黙的にTにint型に変換することができるはずです。しかし、コンパイラはその推論に従うように設計されていないので、Tは、int型であることを確認することを考えています一般的にTはintから派生しないので、暗黙の変換は許可されません。 (コンパイラがそれをサポートしている場合と、検証者はいないだろうので、コンパイルされたアセンブリが検証できないであろう。) – JGWeissman

答えて

99

のタイプをオンに切り替えると、いつでも間違っていると思われます。ジェネリックはgenericです。 は、タイプから完全に独立して動作する必要があります。

Tがintまたはstringのみである場合は、最初にこの方法でコードを記述しないでください。 intを返すメソッドと文字列を返すメソッドの2つのメソッドを記述します。

+2

これは間違っているときに詳しく説明できますか? –

+1

車がIConvertibleを実装すると破損する場所を取得します。あなたが一般的な方法を持っていると誰かが見たら、IConvertibleを実装するものを渡すことができると仮定します。 – Tjaart

+5

私は一部だけあなたに同意することができます。@Eric。私はXML-tagsに格納された配列を解析する必要がある状況があります。問題は、XMLドキュメントが従う仕様です(私の場合はCOLLADA)あなたは配列として文字列を解析する必要があります:float型、int型やブール値だけでなく、いくつかのカスタムtypes.Howeverだけではないが(float_array店が浮く配列タグはその名前で保存されたデータの種類が含まれている)[]あなたはフロートを取得した場合にも使用されるいくつかのするIFormatProviderを必要と山車)の.Iは明らかに「T.Parse(...)」を使用することはできません。だから私は、このような切り替えを使用する必要がある場合の小さなサブセットのために。 – rbaleksandar

9
public T Get<T>(Stats type) where T : IConvertible 
{ 
    if (typeof(T) == typeof(int)) 
    { 
     int t = Convert.ToInt16(PlayerStats[type]); 
     return t as T; 
    } 
    if (typeof(T) == typeof(string)) 
    { 
     string t = PlayerStats[type].ToString(); 
     return t as T; 
    } 
} 
+2

'リターン(T)T;'ヌルチェックは必要でないからです。 – BoltClock

+1

条件がヌルでない場合 –

+0

ハ! +1:私は別の問題を抱えていましたが、Tが私のためにそれを解決したので、戻りません。どうも。 – CodeChops

95

あなただけのカスタムコードの代わりにConvert.ChangeType()を使用することができるはずです。

public T Get<T>(Stats type) where T : IConvertible 
{ 
    return (T) Convert.ChangeType(PlayerStats[type], typeof(T)); 
} 
+2

はどのように 'リターン(T)(オブジェクト)PlayerStats [タイプ]についての完全 –

+7

働くことをありがとう;' – maxp

+0

が答えを提供していただきありがとうございます。絶対とは絶対言うな"。 – mikesigs

3

あなたがTypeConverterを必要とするように見え、this blog entryを参照してください。

6

ChangeTypeが最適です。私のソリューションは、BrokenGlassがtry catchロジックを少し用意したものと似ています。

static void Main(string[] args) 
{ 
    object number = "1"; 
    bool hasConverted; 
    var convertedValue = DoConvert<int>(number, out hasConverted); 

    Console.WriteLine(hasConverted); 
    Console.WriteLine(convertedValue); 
} 

public static TConvertType DoConvert<TConvertType>(object convertValue, out bool hasConverted) 
{ 
    hasConverted = false; 
    var converted = default(TConvertType); 
    try 
    { 
     converted = (TConvertType) 
      Convert.ChangeType(convertValue, typeof(TConvertType)); 
     hasConverted = true; 
    } 
    catch (InvalidCastException) 
    { 
    } 
    catch (ArgumentNullException) 
    { 
    } 
    catch (FormatException) 
    { 
    } 
    catch (OverflowException) 
    { 
    } 

    return converted; 
} 
4

GUIDタイプに対してサポートされていない@BrokenGlassロジック(Convert.ChangeType)を考慮しました。

public T Get<T>(Stats type) where T : IConvertible 
{ 
    return (T) Convert.ChangeType(PlayerStats[type], typeof(T)); 
} 

エラー: '可能System.Guid' から '可能System.String' から無効なキャスト。

代わりにTypeDescriptor.GetConverterのロジックを使用してSystem.ComponentModel名前空間を追加します。

public T Get<T>(Stats type) where T : IConvertible 
{ 
    (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(PlayerStats[type]) 
} 

thisを読んでください。

5

これを試してみてください:

public T Get<T>(Stats type) where T : IConvertible 
{ 
    if (typeof(T) == typeof(int)) 
    { 
     return (T)(object)Convert.ToInt16(PlayerStats[type]); 

    } 
    if (typeof(T) == typeof(string)) 
    { 

     return (T)(object)PlayerStats[type]; 
    } 
} 
+0

これは助けてくれてありがとう、私のニーズは異なっています。私はそれをテストできるように、既存の静的メソッドのモックメソッドを書いています。この使用http://osherove.com/blog/2012/7/8/faking-static-methods-in-moq-fakeiteasy-and-nsubstitute-migh.html – Esen

0

実は、あなただけのTに、その後objectに変換することができます。 boolため

T var = (T)(object)42;

例:

public class Program 
{ 
    public static T Foo<T>() 
    { 
     if(typeof(T) == typeof(bool)) { 
      return (T)(object)true; 
     } 

     return default(T); 
    } 

    public static void Main() 
    { 
     bool boolValue = Foo<bool>(); // == true 
     string stringValue = Foo<string>(); // == null 
    } 
} 

時には、この動作が望ましいです。たとえば、基本クラスまたはインタフェースから汎用メソッドを実装またはオーバーライドするときに、Tタイプに基づいていくつかの異なる機能を追加する場合などです。

関連する問題