2011-10-06 12 views
6

私は流暢な拡張メソッドを試しています。一般的な制約を値型で使用する

安全なキャストを実行する次の簡単な拡張方法があります。

 public static T As<T>(this Object source) 
     where T : class 
    { 
     return source as T; 
    } 

これはうまく働いたが、私は問題に走った過負荷

 public static T As<T>(this ValueType source) 
     where T : struct 
    { 
     return (T)source; 
    } 

と値型を使用することを直感的にしようとしたとき。メソッド解決ロジックは、常に上記の最初のメソッドを選択し、構造体がクラスではない(正確に)構文エラーを返します。

上記を処理する方法はありますか、または同じメソッドですべての型をテストして処理するときに制約を削除する方法はありますか?

====編集:質問に答えるため====

私は3.5フレームワークに対して、これをコンパイルしています。私は特に何かを達成しようとはしていません。これは上記の実験に過ぎません。私の興味は盛り上がり、いくつかのコードをまとめました。

私は特に「安全な」キャストに残っているとは心配していません。それがどのように始まり、デフォルト()で安全に保つことができるのですか?それは本当に安全性を確保するための質問とコードの焦点では​​ありません。

表現力に関しては、value.As<int>()はもはや(int)valueより表現力がありません。しかし、なぜメソッドのユーザーは参照型でしか動作しないということを「ちょうど知っている」必要がありますか?私がそれを働かそうとするのは、表現力豊かな文章よりも、その方法の期待される振る舞いに関するものでした。

コードスニペットvalue.As<DateTime>()は、「型 'System.DateTime'は汎用型またはメソッドでパラメータ 'T'として使用するために参照型でなければなりません。 。エラーメッセージから、参照型を必要とするため、上記のtopメソッドを使用することが解決されていることがわかります。

+0

のC#のバージョンは何よりも使いやすくなって、どのように使っていますか? .NET 4では、2番目のオーバーロードが選択されます。 –

+1

'object o = 42;のようなコードですか? var i = o.As (); 'これは構文エラーですか?または、それを与える正確なコードを表示できますか? – svick

+0

@ svickのコメントは、たとえば、DataRowのようなデータベース結果を使ってやっているかもしれないことを私の心にもたらします。その場合は、行のオブジェクト値を適切な型に変換するための拡張メソッドがすでに用意されています。 [.Field ](http://msdn.microsoft.com/en-us/library/bb360891.aspx) –

答えて

3

.NET 4では、コードサンプルに基づいて2番目のオーバーロードが選択されています。 (.NET 3.5と同じ結果をテストしただけです)

int myInt = 1; 
long myLong = myInt.As<long>(); // chooses ValueType version 

しかし、これは次のクラッシュのシーンに私たちをもたらします。 (T)source;は、無効なキャスト例外を発生させます。あなたはことが

public static T As<T>(this ValueType source) 
    where T : struct 
{ 
    return (T)Convert.ChangeType(source, typeof(T)); 
} 

ような方法を書くことで周りに得ることができる、私はあなたが実際に私はすぐに利益が表示されないように、達成するために探しているのだろうか。 (そして、そのことについては、これはsource as Tオブジェクト・バージョンのような安全ではありません。)例えば

long myLong = myInt.As<long>(); 

どれより表現または

long myLong = (long)myInt; 
+0

ValueTypeは実際にはクラス型であるにもかかわらず、後者の形式では引数。残念なことに、私は本当に.netを汎用パラメータの値の型に基づいてオーバーロードさせる方法はないと考えています。 – supercat

関連する問題