繁体   English   中英

两个类型参数之间的等式约束

[英]Equality constraint between two type parameters

我有以下问题:

界面:

public interface IReader<TOut>
{
    IEnumerable<TOut> GetData(int from, int size);

    TOut Read<TKey>(TKey input);
}

然后我有几个像这样的实现:

    public class ConcreteReader<TOut> : IReader<TOut>
    {
        private IReader<TOut> parentReader;

        public IEnumerable<TOut> GetData(int from, int size)
        {
            // do stuff, don't need TKey for this
        }

        public TOut Read<TKey>(TKey Input)
        {
            this.parentReader.Read(input);
            ... // Do my job
            return result;
        }
    }

但其中一人已经知道TKey:

public class MultiReader<TKey, TOut> : IReader<TOut>
{
    public IEnumerable<TOut> GetData(int from, int size)
    {
        // do stuff. need TKey here
    }

    // this method does the job but it can't be the implementation of IReader<TOut>.Read<TKey>
    public TOut Read(TKey input)
    {
        ...
    }

    // this is the implementation of IReader<TOut>.Read<TKey>
    // I would like to enforce TKey == TKey1 but I can't write 
    // where TKey1 : TKey because the constraint would have to be on IReader interface
    public TOut Read<TKey1>(TKey1 input)
    {
        ...
    }
}

基于另一篇文章我能够写:

public TOut Read<TKey1>(TKey1 input)
{
    if (input is TKey)
    {
        object objectId = (object)input;
        TKey keyId = (TKey)objectId;
        return this.Read(keyId);
    }

    throw new InvalidOperationException();
}

但我发现它非常难看。

有更好的选择吗? 我希望这个解释很清楚。

谢谢你的帮助。

如果你不打算将MultiReader用作IReader那么为什么还要打扰它实现IReader接口呢? 我们的想法是,您可以将引用存储为IReader,并将该对象与实现IReader任何其他类型交替使用。 MultiReader似乎并非如此。

在我看来, MultiReader不应该实现IReader因为你似乎不打算通过IReader接口使用它。 警惕违反Liskov替代原则

由于IReader<TOut>是合约,因此无法隐藏该方法。 接口需要符合指定cotnract签名的公开方法。 但是......你可以通过显式接口实现在这里做一些小技巧:

public class MultiReader<TKey, TOut> : IReader<TOut>
{
    public TOut Read(TKey input)
    {
        return ((IReader<TOut>)this).Read<TKey>(input);
    }

    TOut IReader<TOut>.Read<TKey1>(TKey1 input)
    {
         if (input is TKey)
        {
            object objectId = (object)input;
            TKey keyId = (TKey)objectId;
            return this.Read(keyId);
        }

        throw new InvalidOperationException();
    }
}

然后:

var mr = new MultiReader<string, string>();
var test = mr.Read("someKey"); //OK
var test2 = mr.Read<int>(1); //compile-time error

但你仍然可以做到

var mr = new MultiReader<string, string>();
var test = mr.Read("someKey"); //OK
var test2 = ((IReader<string>)mr).Read<int>(1); //that is ok,
                                                //we use contract - we cannot prevent this

这就是为什么你仍然需要在实现中进行强制检查。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM