2016-06-12 8 views
0

C#コンパイラは、クエリ式の構文からモナドの関連する演算子メソッドへの呼び出しに変換するとき、モナドがいくつかのインターフェイスを実装していることを本当に気にせず、必要としないことを思い出してください。LINQが提供するコンポジションにモナドが参加するための最小限の要件は何ですか?

拡張子または実際のインスタンスメソッドである演算子メソッドについては気にしません。

しかし、詳細は全く思い出せません。 シーケンス自体の最低要件があるようですが、これは下のクエリでnew Foo<string>()の式になります。

インターフェイスに必ずしも従う必要はありませんが、GetEnumeratorという名前のメソッドを持つ必要があったか、IEnumerator<T>メソッドを実装する必要がありました。しかし、私は下の例のクエリがFoo<T>クラスにGetEnumeratorメソッドがあるかどうかに関係なく動作するので間違っている可能性があります。

しかし、whereというクエリ式を導入すると、受信者の種類が解決されません。

Select式はうまくいきます。

私は18ヵ月前までこれを知っていましたが、これは簡単なLINQプロバイダを実装した時です。私はそれ以来ずっとそれを忘れてしまった。

このすべての機能が動作するための最小限の要件をリストしてください。

using System; 

namespace CompilerDoesNotCareAboutTypeLINQQuerySyntax 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      // What are the minimum requirements on Foo<T>()? 
      // How does it resolve this expression new Foo<string> 
      // such that it knows that Foo<string> has many Bar<string> 
      // or whatever foo in the query below might resolve to? 
      var query = from foo in new Foo<string>() 
         /* where foo. // when I do foo., only the system.object inherited properties of Foo show up */ 
         select foo; 
     } 
    } 

    public class Foo<T> 
    { 
     public string Name { get; set; } 

     public Foo<T> Where<T>(Func<T, bool> predicate) 
     { 
      return new Foo<T>(); 
     } 

     /*IEnumerator<Foo<T>> GetEnumerator() 
     { 
      return new List<Foo<T>>().GetEnumerator(); 
     }*/ 
    } 

    public static class Extensions 
    { 
     public static Foo<R> Select<T, R>(this Foo<T> foo, Func<T, R> transformer) 
     { 
      return new Foo<R>(); 
     } 
    } 
} 

更新

ここServyが指摘し修正を実施した後Whereメソッド宣言の更新です。

system.objectに解決上記のクエリ式クエリ内のどの fooに起因するバグを修正し
class Foo<T> 
{ 
    public Foo<T> Where(Func<T, bool> predicate) 
    { 
    return new Foo<T>(); 
    } 
} 

。しかし、今度はstringに解決されます。これは、推論によってWhereメソッドのジェネリック型パラメータ型です。

Servyが指摘し、今では、宣言する型Foo<T>のジェネリック型パラメータである、Tに解決として、私はジェネリック型パラメータTをオーバーロードしていたので、それ以前objectに解決。

まだ質問が残っています: シーケンス式new Foo<string>()の最小必要条件は何ですか?何もないように見える?次に、シーケンスの場所に置かれる式の値と範囲変数fooの型の間の相関関係は何ですか? new Foo<T>多くのfooを返し、クエリfrom foo in new Foo<T>()...fooFoo<T>に解決された場合、何をする必要がありますか?

答えて

1

Whereの実装でTがオーバーロードされています。

あなたは型自体のジェネリック引数としてTを定義し、あなたWhere方法への一般的な引数としてTを定義します。メソッドの引数が "より近い"ため、優先されます。これは、のFunc<T, bool>がメソッド引数のT *であることを意味しますが、クラスのTではありません。 クラスのTはですが、メソッドのTは何かであると推測できません。そのため、パラメータのメンバーはstringではありません。

この場合、タイプ自体はすでに汎用引数を提供しているため、メソッドが汎用である必要はありません。そのメソッド自体が拡張メソッドでない場合、そのメソッドが汎用である必要があります。メソッドをジェネリックではなく、あなたのコードは正常に動作します。

+0

ありがとうございます。私の悪い。それで、何にも合致するための何かの必要性は絶対にありません。 –

+0

あなたが強調表示した問題を修正した後、 'where foo.'を実行すると' foo'が 'string'に評価されるのはなぜですか? –

+0

@ WaterCoolerv2型の汎用引数は 'string'であり、同じ汎用引数はメソッドのパラメータであるため、文字列でなければなりません。 – Servy

関連する問題