4

私は単純なパーサーを書き、次の 2 つのインターフェースを実装したいと考えています。

public interface IResult<TValue, TToken> 
    where TToken : ITokenizer<IResult<TValue, TToken>, TValue>
{
    TToken Tokenizer { get; }
    TValue Value { get; }
}

public interface ITokenizer<TResult, TValue> 
    where TResult : IResult<TValue, ITokenizer<TResult, TValue>>
{
    TResult Advance();
}

次の目的があります:ITokenizer文字列をトークンで分割するための不変クラスです。Advanceメソッドを呼び出してResult、次のトークンと次のトークナイザーを取得できます。したがって、トークンとトークナイザーをResultクラスに保存し、これにコンパイル時の制約を追加したいと考えています。

この 2 つのインターフェイスの構築中にコンパイル エラーが発生しました。

次のクラスは、すべての制約を持つインターフェイスを実装できると思いました。

public class Result : IResult<string, Tokenizer>
{ /* implement interface */}

public class Tokenizer : ITokenizer<Result, string>
{ /* implement interface */}

誰が何が悪いのか説明できますか? なぜそれが不可能なのか、またはこのコードを正しくするにはどうすればよいのでしょうか?

PS私の仕事ではIResult<TValue, TToken>、制約なしで単純にインターフェイスを使用できますが、制約を失うことなくこれを実装できますか?

コンパイラ エラー:

(3:22) The type 'Test.IResult<TValue,TToken>' cannot be used as type parameter 'TResult' in the generic type or method 'Test.ITokenizer<TResult,TValue>'. 
There is no implicit reference conversion from 'Test.IResult<TValue,TToken>' to 
'Test.IResult<TValue,Test.ITokenizer<Test.IResult<TValue,TToken>,TValue>>'.
(10:22) The type 'Test.ITokenizer<TResult,TValue>' cannot be used as type parameter 'TToken' in the generic type or method 'Test.IResult<TValue,TToken>'. 
There is no implicit reference conversion from 'Test.ITokenizer<TResult,TValue>' to 
'Test.ITokenizer<Test.IResult<TValue,Test.ITokenizer<TResult,TValue>>,TValue>'.
4

2 に答える 2

0

更新 Evk の回答がこの回答を否定したため、この回答は無視してください。ただし、他の誰かが循環参照に関係していると考えている場合は、明らかにそうではないことを説明するのに役立つため、この回答をここに残しておきます。

問題は、コンパイラが最初のインターフェイスをコンパイルしようとするときに、2 番目のインターフェイスをコンパイルする必要がありますが、2 番目のインターフェイスをコンパイルするには、最初のインターフェイスをコンパイルする必要があることです。したがって、結論に達することができないので、そうすることができません。物事を簡単にするために、このコードはあなたのものと同じエラーを受け取ります:

public interface IFirst<TFirst>
    where TFirst : ISecond<IFirst<TFirst>>
{

}

public interface ISecond<TSecond>
    where TSecond : IFirst<ISecond<TSecond>>
{ }

ただし、循環参照がなく、コンパイラが結論に達することができるため、以下のコードではエラーが発生しません。

public interface IFirst<TFirst>
    where TFirst : ISecond<IFirst<TFirst>>
{

}

public interface ISecond<TSecond>
    //where TSecond : IFirst<ISecond<TSecond>>
{ }
于 2016-11-19T16:41:26.180 に答える