2

私は例で私の質問を説明しようとします:

class V<T>
{
    public readonly Func<T> Get;
    public readonly bool IsConstant;

    V(Func<T> get, bool isConstant)
    {
        Get = get;
        IsConstant = isConstant;
    }

    public static implicit operator V<T>(T value)
    {
        return new V<T>(() => value, true);
    }

    public static implicit operator V<T>(Func<T> getter)
    {
        return new V<T>(getter, false);
    }
}

void DoSomething<T>(V<T> v)
{
    //...
}

void Main()
{
    DoSomething<string>("test"); // (1) type inference is not working
    DoSomething<string>((V<string>)(() => "test")); // (2) implicit operator does not work
}

この方法Mainでは、次の2つの状況があります。

  1. <string>メソッドの総称引数を明示的に指定する必要がありますDoSomething
  2. ここで、明示的なキャストを追加する必要があり(V<string>)ます。暗黙的な演算子は機能していないようです。

なぜこれが必要なのですか?コンパイラが検討している代替案は何ですか?正しい方法を選択できませんか?

4

3 に答える 3

5

2番目の質問は、に変換可能であり、に変換可能であるにもかかわらず、からへの暗黙の変換が成功しない()=>""理由です。V<string>()=>""Func<string>Func<string>V<string>

繰り返しますが、「どうして?」と答える方法がわかりません。質問ですが、「仕様のどの行が、コンパイラがこのコードを拒否する必要があることを示していますか?」という質問に答える方法を知っています。関連する行は次のとおりです。

まず、必要に応じて、ソースタイプからユーザー定義またはリフトされた変換演算子のオペランドタイプへの標準変換を実行します。

ここに小さなエラーがあることに注意してください。これは、ソース式から標準変換を実行することを意味するはずです。ソース式に型がない場合があります。チームを去る前にスペックメンテナーにそのメモをしたと思うので、これが次の版で修正されることを願っています。

とにかく、ここで何が起こっているのかが明確になっているはずです。ラムダからデリゲート型への標準的な変換はないため、ユーザー定義の変換は、変換解決アルゴリズムによって適用不可として分類されます。

于 2013-01-02T01:40:10.097 に答える
3

あなたのコードは、DumpValue ではなく DoSomething を呼び出すことを意図していたと思います。

あなたの質問は、まず、なぜ

DoSomething("");

呼び出しが意図されていると推測しないでください

DoSomething<string>((V<string>)"");

正しい?

「なぜ」という質問は答えるのが非常に難しく、「なぜしないのですか?」質問はさらに難しいです。代わりに、答えることができる質問に答えます:仕様のどの行がこの動作を正当化しますか?

オーバーロード解決は次のように機能します。メソッド グループにジェネリック メソッドが含まれているが、ジェネリック メソッドの型引数が指定されていない場合、型推論は型引数を推論しようとします。型引数を推論できない場合、そのメソッドはオーバーロード解決の対象から除外されます。あなたの場合、メソッド グループにはメソッドが 1 つしかないため、それを削除すると、オーバーロードの解決が失敗します。

では、なぜ型推論が失敗するのでしょうか? 仕様の制御行が次のとおりであるため、T を推測できません。

V が構築された型C<V1…Vk>であり、U から U への標準の暗黙的な変換が存在するように型 U1…Uk の一意のセットがあるC<U1…Uk>場合、対応する Vi の各 Ui から正確な推論が行われます。

からへの標準の暗黙的な変換はありません。これは、ユーザー定義の暗黙的な変換です。stringV<string>

したがって、型推論は失敗します。

2 番目の回答で 2 番目の質問にお答えします。一般に、1 つの質問で 2 つの質問をするのはよくありません。質問が 2 つある場合は、質問を 2 つ投稿してください。

于 2013-01-02T01:27:53.607 に答える
0

あなたの質問が「なぜ型推論が機能しないのか」だったのは知っていますが、2つの選択肢について最後にあなたの声明を取り上げたいと思いました。この場合、暗黙の変換(ええと、私はそれらが嫌いです)のより良い代替手段は静的ファクトリメソッドであると私は信じています。IMO、を呼び出すと構文が改善されますDumpValue

static class VFactory
{
    public static V<T> Create<T>(T value)
    {
        return new V<T>(() => value, true);
    }

    public static V<T> Create<T>(Func<T> getter)
    {
        return new V<T>(getter, false);
    }
}

class V<T>
{
    public readonly Func<T> Get;
    public readonly bool IsConstant;

    internal V(Func<T> get, bool isConstant)
    {
        Get = get;
        IsConstant = isConstant;
    }
}

void DumpValue<T>(V<T> v)
{
    //...
}

void Main()
{
    DumpValue(VFactory.Create("test"));
    DumpValue(VFactory.Create(() => "test"));
}
于 2013-01-02T04:50:49.287 に答える