開発ブログ、オンラインのコード例、そして(最近では)本でも、次のようなコードによく遭遇します。
var y = x as T;
y.SomeMethod();
さらに悪いことに:
(x as T).SomeMethod();
それは私には意味が分かりません。 がx
タイプ であることが確実な場合はT
、直接キャスト を使用する必要があります: (T)x
。確実でない場合は を使用できますas
が、何らかの操作を実行する前に を確認する必要があります。上記のコードが行うことは、 (有用な)を (役に立たない) にnull
変換することだけです。InvalidCastException
NullReferenceException
これはキーワードの露骨な乱用だと思うのは私だけでしょうかas
? それとも、私が何か明らかなことを見逃していて、上記のパターンは実際に意味をなしているのでしょうか?
ベストアンサー1
あなたの理解は正しいです。それは、マイクロ最適化を試みているように私には聞こえます。型が確実な場合は、通常のキャストを使用する必要があります。より合理的な例外を生成するだけでなく、失敗も早くなります。型についての仮定が間違っている場合、プログラムはすぐに失敗し、将来的にNullReferenceException
orArgumentNullException
または論理エラーが発生するのを待つのではなく、失敗の原因をすぐに確認できます。一般的に、どこかでチェックas
が行われていない式は、null
コード臭です。
一方、キャストが確実でなく、失敗すると予想される場合は、ブロックas
で囲まれた通常のキャストの代わりにを使用する必要がありますtry-catch
。さらに、型チェックの後にキャストするよりも の使用がas
推奨されます。 の代わりに:
if (x is SomeType)
((SomeType)x).SomeMethod();
生成するisinst
命令キーワードとしてis
、castclass
命令キャスト(実質的にキャストを 2 回実行する)には、以下を使用する必要があります。
var v = x as SomeType;
if (v != null)
v.SomeMethod();
これは命令を生成するだけですisinst
。前者の方法は、マルチスレッド アプリケーションでは潜在的な欠陥があり、競合状態により、チェックが成功した後に変数の型が変更されis
、キャスト行で失敗する可能性があります。後者の方法では、このエラーは発生しません。
次のソリューションは、実稼働コードでの使用は推奨されません。C# のこのような基本的な構造が本当に嫌な場合は、VB または他の言語に切り替えることを検討してください。
キャスト構文がどうしても嫌な場合は、キャストを模倣する拡張メソッドを書くことができます。
public static T To<T>(this object o) { // Name it as you like: As, Cast, To, ...
return (T)o;
}
そして、きちんとした[?]構文を使用します:
obj.To<SomeType>().SomeMethod()