![](/img/trans.png)
[英].NET 4.8 + checking equality between two generic type parameters in the Where clause
[英]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.