2012-05-02 14 views
2

私は、ジェネリックメソッドをパラメータとして渡す(this)という基本クラスのメソッドがある状況で自分自身を見つけました。ジェネリックメソッドでは、派生クラスからメソッドを呼び出すときでも、型は常に基本型です。typeofこれは、派生クラスから呼び出される仮想メソッド

基本型ではなく、派生型であることを知るには汎用メソッドが必要です。

サードパーティのアプリ(http://razorengine.codeplex.com/ - Razor.Parseメソッド)からのものであるため、汎用メソッドを変更することはできません。

私は、メソッドをジェネリック拡張メソッドとして定義すると、これを呼び出すのが基本クラスから継承する型に限定されているが、この目的のために拡張メソッドを使用するのが面倒だと分かったそれを聞いてうれしいです)。私はそれが呼び出される前に(おそらくジェネリックスを使用して)派生オブジェクトの型に "this"を変換するために使用できるトリックがあるかどうか疑問に思っています。

私は自己完結型でなければならない以下のような単純化されたプログラムを含んでいます(私はLINQPadで簡単に実行しています)。基本的には、Bのインスタンスで呼び出されたときTest.WhatTypeと出力 "B"を呼び出すAで定義されたメソッドが必要です。

これは意味があると思います。

void Main() 
{ 
    var bar = new B(); 
    bar.myGetType(); 
    bar.ExtGetType(); 
} 

class A 
{ 
    public virtual void myGetType() 
    { 
     Test.WhatType(this); 
     this.ExtGetType(); 
    } 
} 

class B : A {} 

static class ext 
{ 
    public static void ExtGetType<T>(this T obj) where T : A 
    { 
     Test.WhatType(obj); 
    } 
} 

class Test 
{ 
    public static void WhatType<T>(T obj) 
    { 
     Console.WriteLine(typeof(T).Name); 
    } 
} 

編集:私も、私が誤って過負荷に気づいたしていなかったので、A.myGetType()から変更メソッド名。

N.B.このコードを実行すると、次のように出力されます。

A 
A 
B 
+0

あなたの一般的な方法は、種類を気にした場合、過去 'ここで、T:A'その後、その方法を再評価する必要があります。 – cadrell0

+0

まあ、ちょっと間違いありません - 呼び出しコードはクラスAです! (私はそれが役に立たないことを知っています)私は掘り出し物を持って、あなたに戻ってみるよ! –

+0

WhatTypeメソッドではなく、obj.GetType()を使用する必要があります。 –

答えて

2

私が正しく理解していれば、A.GetType()WhatType<A>にバインドされているので、それはすべて知っているからです。

したがって、クラスAに派生クラスについて知らせなければなりません。

これは、自己参照型ジェネリック型で行うことができます。何かのように:その後、

class A<T> where T : A<T> 
{ 
    public virtual void GetType() 
    { 
     Test.WhatType<T>((T) this); 
    } 
} 

class B : A<B> { } 

new B().GetType(); 

WhatType<B>に結合してますので、出力するであろうB

+0

ああ、これは私が不思議に思っていたようなものでした。私は解決策としてそれが見えるかどうかは分かりませんが、それはどんな些細なものでもありませんが、共有していただきありがとうございます。これは確かに一般的に役立つように見えます。 :) – Chris

+0

'A.GetType()'の中から拡張メソッドを呼び出すと 'A'が出力されます - ' B'を出力したいと思ったのですか? –

+0

私はあなたのフォローアップの質問を理解しているか分からない。 – Chris

-1

このメソッドは、静的型(T)の型を返します。 私はちょうどあなたが欲しいものを実現し、一般的な方法の変更のTようにAを操作することである:それは

public static void WhatType<T>(T obj) 
{ 
    Console.WriteLine(obj.GetType().Name); 
} 

編集として実装する必要があります。リフレクションを介して、またはAのサブタイプに基づいてswitch文を追加して、これをB(またはどんなクラス)にも明示的にキャストできます。もちろん、Aがそのサブクラスと反射を明白にsuxに依存するので、このソリューションのどれも良いものではありません。もう1つの方法は、各サブクラスのGetType()メソッドをオーバーライドして、その責任をサブクラスに移すことです。

+1

にはタイプが必要です。私はあなたがobj.GetType()を意味すると思う – cadrell0

+1

これは決してコンパイルされません。 'obj'は' typeof'に対して有効なパラメータではありません。型名が必要です。 – jason

+0

あなたは正しいです。一定。 – Stilgar

3

obj.GetType()を使用する必要があります。 Tは実行時ではなくコンパイル時にバインドされるため、typeof(T)はコンパイル時の型をTに返します。

+0

Ah。はい、私のテストは間違っていました。 'Test.WhatType'は、代わりに基本クラスとして渡されたパラメータを考慮していると思われる第三者のアプリケーションの静的メソッドのシミュレーションであった。私の問題は実際にはRazorEngineライブラリにあるようです。私はそこを見に行きます。助けてくれてありがとう。 :) – Chris

+0

実際、私が呼んでいた 'Razor.Parse'メソッドは、' mode.GetType() 'ではなく' typeof(T) 'を使用しているようです。私は彼らに文句を言うだろうと思う。 ;-) – Chris

関連する問題