[解決済み] GetType()は嘘をつくのか?
質問
数日前にSOで行われた以下の質問に基づいています。
GetType()とポリモーフィズム
と読みます。
Eric Lippert の
の回答を読んで、もし
GetType()
を仮想化しないようにすることで、本当にオブジェクトがその
Type
.
具体的には、Ericの回答には次のように書かれています。
フレームワークの設計者は、オブジェクトが単に同じ型上の他の3つのメソッドと一貫性を持たせるために、その型について嘘をつくことを許すような信じられないほど危険な機能を追加するつもりはないでしょう。
今問題なのは、オブジェクトが を行う がその型について嘘をつくことを、すぐにわかるようにできるでしょうか?私はここで深く間違っているかもしれませんし、もしそうであれば説明を求めますが、次のコードを考えてみてください。
public interface IFoo
{
Type GetType();
}
そして、当該インタフェースの次の2つの実装です。
public class BadFoo : IFoo
{
Type IFoo.GetType()
{
return typeof(int);
}
}
public class NiceFoo : IFoo
{
}
次に、以下のような簡単なプログラムを実行すると
static void Main(string[] args)
{
IFoo badFoo = new BadFoo();
IFoo niceFoo = new NiceFoo();
Console.WriteLine("BadFoo says he's a '{0}'", badFoo.GetType().ToString());
Console.WriteLine("NiceFoo says he's a '{0}'", niceFoo.GetType().ToString());
Console.ReadLine();
}
案の定
badFoo
は誤った
Type
.
さて、Eric がこの動作を " と表現していることから、これが重大な意味を持つかどうかはわかりません。 非常に危険な機能 しかし、このパターンが信頼できる脅威となる可能性はあるのでしょうか?
どのように解決するのですか?
いい質問ですね。私の見るところ、GetType がオブジェクト上で仮想であった場合のみ、仲間の開発者を本当に誤解させることができます。
あなたがしたことは、このようにGetTypeをシャドーイングすることに似ています。
public class BadFoo
{
public new Type GetType()
{
return typeof(int);
}
}
このクラスで(そして メソッドのサンプルコードです。 を使えば、確かに
int n1 = 12;
BadFoo foo = new BadFoo();
Console.WriteLine("n1 and n2 are the same type: {0}",
Object.ReferenceEquals(n1.GetType(), foo.GetType()));
// output:
// n1 and n2 are the same type: True
というわけで、ヤバイ、嘘に成功しましたね?
まあ、イエスでもありノーでもあるのですが...。これを悪用する場合、BadFooインスタンスをどこかのメソッドの引数として使用することになります。
object
またはオブジェクトの階層のための共通の基本型を期待します。このようなものです。
public void CheckIfInt(object ob)
{
if(ob.GetType() == typeof(int))
{
Console.WriteLine("got an int! Initiate destruction of Universe!");
}
else
{
Console.WriteLine("not an int");
}
}
しかし
CheckIfInt(foo)
は "not an int" と出力します。
つまり、基本的には (あなたの例に戻ると)、誰かがあなたの
IFoo
インターフェイスに対して書かれたコードによってのみ利用可能で、このインターフェイスは "custom" を持つという事実について非常に明確です。
GetType()
メソッドがあることを非常に明確に示しています。
GetType() がオブジェクト上で仮想的であった場合のみ、以下のようなメソッドで使用できる "lying"の型を作成することができます。
CheckIfInt
のようなメソッドで使用され、他の誰かによって書かれたライブラリで大混乱を引き起こすことができる "lying"型を作ることができる唯一のものです。
関連
-
[解決済み】ASP.NET Core Dependency Injectionのエラーです。アクティブ化しようとしているときに、タイプのサービスを解決できません。
-
[解決済み】パディングが無効で、削除できない?
-
[解決済み】C#のequal to演算子でtextとvarcharのデータ型は互換性がない
-
[解決済み] [Solved] .NETでスレッドの終了を待つには?
-
[解決済み】「namespace」なのに「type」のように使われる。
-
[解決済み] intをenumにキャストするにはどうすればよいですか?
-
[解決済み] 型チェック:typeof、GetType、is?
-
[解決済み] ランダムな英数字の文字列を生成するにはどうすればよいですか?
-
[解決済み] .NETコンソールアプリケーションでアプリケーションのパスを取得するにはどうすればよいですか?
-
[解決済み] アセンブリファイルのバージョンを取得する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】スクリプトクラスが見つからないので、スクリプトコンポーネントを追加できない?
-
[解決済み] [Entity Framework 4.1でエンティティに関連オブジェクトを追加する際に、エンティティオブジェクトをIEntityChangeTracker.の複数のインスタンスから参照できない。
-
[解決済み] エンティティタイプ <type> は、現在のコンテキストのモデルの一部ではありません。
-
[解決済み】C#はJavaのcharAt()と同等?)
-
[解決済み】"The ConnectionString property has not been initialized "を修正する方法
-
[解決済み】「namespace x already contains a definition for x」エラーの修正方法は?VS2010にコンバートした後に発生しました。
-
[解決済み] [Solved] 不正な文字列値: '\xEFxBFxBD' for column
-
[解決済み】MetadataException: 指定されたメタデータ・リソースをロードできない
-
[解決済み】Moqを使用してメソッド呼び出しを検証する
-
[解決済み】値をNULLにすることはできません。パラメータ名:source