我想弄清楚为什么在我投射时使用is
关键字似乎有所不同。这是一个显示我正在查看的测试用例:
[TestFixture]
public class TestMy {
public interface IBaseMessage { }
public interface IMessageProcessor<T> where T : IBaseMessage {
void Process(T msg);
}
public class RRMessage : IBaseMessage {
}
public class BaseMessageProcessor {
public bool CanProcess<T>(T msg) where T : IBaseMessage {
return this is IMessageProcessor<T>;
}
}
public class RRMessageProcessor : BaseMessageProcessor, IMessageProcessor<RRMessage> {
public void Process(RRMessage msg) {
throw new NotImplementedException();
}
}
[Test]
public void Test1() {
var msgProcessor = new RRMessageProcessor();
var msg = new RRMessage();
Console.WriteLine(msgProcessor.CanProcess(msg));
}
[Test]
public void Test2() {
var msgProcessor = new RRMessageProcessor();
var msg = new RRMessage() as IBaseMessage;
Console.WriteLine(msgProcessor.CanProcess(msg));
}
为什么Test1()返回True
而Test2()返回False
。如何实施CanProcess()
以便在两种情况下都返回True
?
答案 0 :(得分:4)
Test1
中的类型推断意味着它正在调用
msgProcessor.CanProcess<RRMessage>()
...而Test2
正在调用
msgProcessor.CanProcess<IBaseMessage>()
现在RRMessageProcessor
未实现IMessageProcessor<IBaseMessage>
- 您无法调用Process(justAnyMessage)
- 仅知道如何处理RRMessage
值。所以这基本上是完全合理的。
要使两个测试都返回true,您实际上并不需要通用方法,因为您只关心msg
的执行时类型。这里有几个选项:
使用私有泛型方法,但使用类型为dynamic
的参数调用它,在这种情况下,将使用消息的执行时类型执行类型推断:
public bool CanProcess(IBaseMessage message)
{
dynamic d = message;
// Perform type inference at execution time
return CanProcess(d);
}
private bool CanProcess<T>(T message)
{
return this is IMessageProcessor<T>;
}
使用反射检查界面,例如致电typeof(IMessageProcessor<>).MakeGenericType(msg.GetType()).IsAssignableFrom(GetType())
请注意,您仍然需要小心谨慎 - 假设您有一些来自SpecialRRMessage
的{{1}} ...然后RRMessage
仍然可以合理地处理它,但它不会实施RRMessageProcessor
。
您可能想要更改IMessageProcessor<SpecialRRMessage>
界面,以便IMessageProcessor<T>
被宣布为逆变:
T
此时,由于违反,您的public interface IMessageProcessor<in T> where T : IBaseMessage
将实施RRMessageProcessor
。