2012-03-07 11 views
13

とデリゲートに拡張メソッドグループの変換:は、私は、次のシグネチャを持つのIDataReader上の2つの拡張メソッドを持つジェネリック型

internal static List<T> GetList<T>(this IDataReader reader, Func<string, T> del) 

internal static double? GetDoubleOrNull(this IDataReader reader, string columnName) 

GetDoubleOrNullは、任意の過負荷を持っていません。

他の場所で、私は

Func<string, double?> del = reader.GetDoubleOrNull; 

var x = reader.GetList(del); 

または

var x = reader.GetList<double?>(reader.GetDoubleOrNull); 

か、単に

public double? blah(string s) 

var x = reader.GetList(blah); 

のようなインスタンスメソッドに渡すが、私は

を行うことはできませんを行うことができますよ
var x = reader.GetList(reader.GetDoubleOrNull); 
私はこのことを理解していない

コンパイラはエラーに

cannot convert from 'method group' to 'System.Func<string,double?>' 

を与えます。私はGetDoubleOrNullに過負荷がないので、過負荷の解決はなく、メソッドのシグネチャから型パラメータを推測できると思っていました。

実際に混乱している部分は、blahを渡すとうまくいくようです。

+3

非常に興味深い。明示的キャスト '' var x = reader.GetList((Func )リーダです。GetDoubleOrNull) ''も動作します。 Resharperはキャストを冗長としてマークしますが、コンパイルが失敗すると失敗します。 Jon Skeetはまわりですか? –

+3

Jon Skeet(またはEric Lippert)を呼び出す方法はありますか?彼らの名前を3回か何か言ってください? – Chris

+1

関連:http://stackoverflow.com/questions/7745852/method-inference-does-not-work-with-method-groupおよびhttp://stackoverflow.com/questions/2057146/compiler-ambiguous-invocation-error -anonymous-method-and-method-group-with-fun – AakashM

答えて

0

GetDoubleOrNullはdoubleを返しますか? GetListのは

公共ダブル誤解を招く少しはあるのIDataReaderとSystem.Func<string,int?>

エラーメッセージを期待しますか? blah(ストリングs)

var x = reader.GetList(blah);

blahはこの呼び出しでは代理人です。 GetList(GetDoubleOrNull)では、get doubleOrNullの結果になります。

良い質問ですが。私が助けたかどうかにかかわらず答えを投稿してください。

+0

'' int''はtypoでなければならず、 '' double''に変更するとコンパイラエラーが発生します。 –

+0

Jacekは正しいです。私の間違い。ごめんなさい。 – Moss

+1

あなたは「GetList(GetDoubleOrNull)ではget doubleOrNullの結果です」と言っていますが、これは正しくありません。この場合、 'GetDoubleOrNull'は評価されておらず、メソッドグループとして扱われています。 – Chris

8

はじめに:完全な説明が必要な場合は、編集をスキップしてください。 Spoiler:拡張メソッドはコンパイラのトリックであり、実際に呼び出すときのように1つ以上の引数を持っています。

これはメソッドグループの解決です。どうやらC#コンパイラは、使用しているメソッドが過負荷かどうかを判断する時間がかかりません。それは常に明示的なキャストが必要です。チェックアウト:

What is a method group in C#?
Method Inference does not work with method group

あなたはそれをキャストしようとするもので絞られるバックreader.GetDoubleOrNullからくる方法グループ:GetDoubleOrNullは、その名前のオーバーロードされた任意の数の方法を参照することができます。明示的にキャストする必要があります。

興味深いことに、あなたも同じ理由で暗黙的に型指定された変数にメソッドグループを割り当てることができません。

var x = reader.GetDoubleOrNull; 

は、それが明示的なキャストが必要なため、コンパイルに失敗しました。

編集私はここで混乱が拡張メソッドに関係していることをかなり確信している:

は、次のテストクラスをチェックアウト:

public static class Extensions 
{ 
    public static List<T> GetList<T>(this IDataReader reader, Func<string, T> del) 
    { 
     throw new NotImplementedException(); 
    } 

    public static double? GetDoubleOrNull(this IDataReader reader, string columnName) 
    { 
     throw new NotImplementedException(); 
    } 

    public static double? blah(this string s) 
    { 
     throw new NotImplementedException(); 
    } 
} 

をあなたは成功し

var x = reader.GetList(Extensions.blah); 
を呼び出すことができます

なぜこれがである可能性がありますか? blahも静的な拡張メソッドなので、あなたの証拠に基づいて、上記の行はコンパイルしないように見えます。さらに物事を複雑、のは、このメソッドを追加してみましょう。

public static List<T> GetList2<T>(this IDataReader reader, Func<IDataReader, string, T> del) 
{ 
    throw new NotImplementedException(); 
} 

あなたは今

x = reader.GetList2(Extensions.GetDoubleOrNull); 

を呼び出すことができ、それが適切にコンパイルします。何がありますか?

ここに答えがあります:拡張メソッドはありません実際にはオブジェクトにメソッドを追加します。実際には、それらのメソッドがクラスの一部であるかのようにプログラムすることができます。 hereから:あなたのコードで

あなたはインスタンスメソッド 構文で拡張メソッドを呼び出します。ただし、コンパイラ によって生成された中間言語(IL)は、コードを静的メソッドの呼び出しに変換します。 したがって、カプセル化の原則は実際には に違反していません。実際に、拡張メソッドは拡張型のプライベート変数 にはアクセスできません。だから、

var x = Extensions.GetDoubleOrNull(reader, "myColumnName"); 

:あなたは(それは拡張メソッドだにも関わらず、完全に合法的な呼び出し)、実際にコンパイルして実行されているもの

var x = reader.GetDoubleOrNull("myColumnName"); 

は、本質的にこれです呼び出すので

GetDoubleOrNullFunc<string, double?>の引数として使用しようとすると、コンパイラは「GetDoubleOrNullFunc<IDataReader, string, double?>にすることができますが、これには2つの引数がありますが、kはしません今では1つの引数とIDataReaderのインスタンスメソッドだかのようにあなたがそれを呼んでいるにもかかわらずFunc<string, double?>

にそれを有効にする方法、それはではない:それはだ2つの引数のC#での静的なメソッドコンパイラはあなたを思考に誘惑して、IDataReaderの一部です。

+0

優れた答えと研究。もう一度+1したいです。 ;-) – Chris

+3

私はJon Skeetではありませんが、私はできることをしています:D – eouw0o83hf

+0

あなたの答えをありがとう。残念ながら、私は問題をはっきりと理解していないようです。 あなたが参照した最初の質問は、私が知っている質問です。私は、AakashMによって投稿されたものと同様に、2番目のものを読みました。そして、それは、オーバーロード解決が戻り値の型をどのように考慮しないかということになります。という事は承知しています。 しかし、どのようにして 'blah'の作業に合格するのですか?その場合、過負荷の解決はありませんか?そうでない場合は、どうしてですか?もしそうなら、それはどのように成功するのでしょうか? – Moss

関連する問題