C#4は“動的キャスト”を許可しますか?そうでない場合、C#はそれをサポートする必要がありますか?
-
03-07-2019 - |
質問
より低いインターフェイスまたはベースクラスをより派生したクラスにキャストするという意味での動的なキャストを意味するのではなく、作成したインターフェイス定義を取得し、そのインターフェイスに異なるオブジェクトを動的にキャストすることそのインターフェースから派生しますが、すべての呼び出しをサポートします。
たとえば、
interface IMyInterface
{
bool Visible
{
get;
}
}
TextBox myTextBox = new TextBox();
IMyInterface i = (dynamic<IMyInterface>)myTextBox;
これは、既知の型のコンパイル時、および動的に宣言されたインスタンスの実行時に達成できます。インターフェース定義は、タイプ(この例では)と同様に既知であるため、コンパイラーは、オブジェクトがインターフェースによって定義された呼び出しをサポートしているかどうかを判断し、キャストさせるための魔法を実行できます。
これはC#4ではサポートされていないと思いますが(それへの参照が見つかりませんでした)、確かに知りたいと思います。そうでない場合は、将来の言語のバリエーションに含める必要があるかどうか、およびその理由と反対について説明します。私にとっては、既存のフレームワーク型をラップするためにまったく新しい型を作成することなく、コードのより大きな多態性を可能にする素晴らしい追加のようです。
更新
誰かが盗作を非難しないように、 Jon Skeetはすでにこれを提案しています。ただし、非常に類似した構文を考えたことを知ってうれしいです。これは、少なくとも直感的なものである可能性を示唆しています。一方、「オリジナルのアイデアを持っている」バケットリストに1日間残ります。
解決
Jon Skeetがそのような提案をしたと思います( http://msmvps.com/blogs/jon_skeet/archive/2008/10/30/c-4-0-dynamic-lt-t-gt.aspx )、しかし、これまでのところ、C#4.0に含まれるとは聞いていません。
他のヒント
それは問題があると思います。結合されていない2つのクラス間に結合を導入しています。
次のコードを検討してください。
public interface IFoo
{
int MethodA();
int MethodB();
}
public class Bar
{
int MethodA();
int MethodB();
}
public class SomeClass
{
int MethodFoo(IFoo someFoo);
}
これは合法ですか?
int blah = someClass.MethodFoo((dynamic<IFoo>)bar);
コンパイラはIFooを実装するものとしてbarを動的に入力できる必要があるため、それは合法であると思われます 。
ただし、この時点では、コードの完全に別の部分で呼び出しを通じてIFooとBarを結合しています。
MethodBが不要になったためにBarを編集すると、BarとIFooが関連していなくても、突然someClass.MethodFoodが機能しなくなります。
同様に、IFooとBarが表面上は関連していない場合でも、MethodC()をIFooに追加すると、コードは再び壊れます。
事実、これは、制御していないオブジェクト間で類似性がある特定の場合に役立ちますが、インターフェイスをオブジェクトに明示的にアタッチする必要がある理由があり、その理由はコンパイラがオブジェクトがそれを実装することを保証します。
ライブラリとして非常にきれいに実装できるため、C#でこれをサポートする必要はありません。
3つまたは4つの別個の実装を見てきました(それらを見つける前に自分で実装を開始しました)。これまで見た中で最も徹底した治療法は次のとおりです。
DLRがランタイムに統合されると、おそらく実装がさらに簡単になります。
特定のインターフェイスのラッパー/フォワーダークラスを1回生成してからキャッシュし、次に不明なタイプの特定のオブジェクトを1回ラップできるため、呼び出しサイトのキャッシュなどのスコープがたくさんあります。パフォーマンスは優れているはずです。
対照的に、 dynamic
キーワードは言語の特徴であり、非常に複雑なものであるため、不必要で悲惨な脱線であり、以前は非常に明確な静的型付けの哲学。これにより、将来の改善のための明確な方向性が与えられました。彼らはそれに固執し、タイピングがより見えなくなるまで、タイプ推論をより良く機能させるべきでした。既存のプログラムを壊すことなく言語を進化させることができる領域は非常に多くありますが、単にリソースの制約のためにそうではありません(たとえば、 var
がより多くの場所で使用できない理由はコンパイラを書き換える必要があり、時間がないためです。)
彼らはC#4.0(分散機能)でまだ良いことをしていますが、コンパイル時に問題を検出する際に型システムをよりスマートに、より自動で、より強力にするためにできることは他にもたくさんあります。代わりに、私たちは本質的に仕掛けを得ています。
オープンソースフレームワーク Impromptu-Interface は、C#4とdlrを使用してこれを行います。
using ImpromptuInterface;
interface IMyInterface
{
bool Visible
{
get;
}
}
TextBox myTextBox = new TextBox();
IMyInterface i = myTextBox.ActLike<IMyInterface>();
dlrを使用するため、ExpandoObjectおよびDynamicObjectでも動作します。