首先,请记住.NET String是IConvertible和ICloneable.
现在,考虑以下非常简单的代码:
//contravariance "in"
interface ICanEat<in T> where T : class
{
void Eat(T food);
}
class HungryWolf : ICanEat<ICloneable>, ICanEat<IConvertible>
{
public void Eat(IConvertible convertibleFood)
{
Console.WriteLine("This wolf ate your CONVERTIBLE object!");
}
public void Eat(ICloneable cloneableFood)
{
Console.WriteLine("This wolf ate your CLONEABLE object!");
}
}
Run Code Online (Sandbox Code Playgroud)
然后尝试以下(在某些方法中):
ICanEat<string> wolf = new HungryWolf();
wolf.Eat("sheep");
Run Code Online (Sandbox Code Playgroud)
当编译它时,没有编译器错误或警告.运行它时,看起来调用的方法取决于我的class声明中的接口列表的顺序HungryWolf.(尝试在逗号(,)分隔列表中交换两个接口.)
问题很简单:这不应该给出编译时警告(或者在运行时抛出)吗?
我可能不是第一个提出像这样的代码的人.我使用了界面的逆变,但你可以用界面的covarainace做一个完全类似的例子.事实上,Lippert先生很久以前就做过这样的事情.在他博客的评论中,几乎每个人都认为这应该是一个错误.然而他们默默地允许这样做. …
这是两种使用的扩展方法
public static Type FindInterfaceWith(this Type type1, Type type2) {
// returns most suitable common implemented interface
}
public static Type FindBaseClassWith(this Type type1, Type type2) {
// returns most derivative of common base class
}
Run Code Online (Sandbox Code Playgroud)
FindInterfaceWith返回null如果他们没有共同实现的接口.FindBaseClassWith返回System.Object,如果他们有没有更多的衍生物共同的基类.FindBaseClassWithnull如果其中一个参数是一个接口,则返回null如果有任何参数,它们都会返回null.最终解决方案中的方法签名如下:
public static Type FindAssignableWith(this Type type1, Type type2) {
// what should be here?
}
Run Code Online (Sandbox Code Playgroud)
反射和Linq仅限使用,除非没有其他方法.
有没有好的方法之间找到共同类型的最适合type1和type2?
或者有更好的事情来实现这一目标吗?
更新:
根据我个人的理解,由于能够使用类实现多个接口, …
破碎的代码
public static partial class LogicExtensions {
public static bool Implies<T>(this T premise, T conclusion) {
return conclusion.Infers(premise);
}
public static bool Infers<T>(this T premise, T conclusion) {
return premise.Implies(conclusion);
}
}
Run Code Online (Sandbox Code Playgroud)上面的代码希望表达:
结论推断了前提,因为前提暗示了结论.
前提暗示了结论,因为结论推断了前提.
这将是循环推理,肯定会导致堆栈溢出.然后我重新设计如下:
工作代码
public delegate bool Paradox<T>(T premise, T conclusion, Paradox<T> predicate=null);
public static partial class LogicExtensions {
public static bool Implies<T>(this T premise, T conclusion, Paradox<T> predicate=null) {
if(null==predicate)
return conclusion.Infers(premise, Implies);
if(Infers!=predicate)
return predicate(premise, conclusion);
return LogicExtensions.Implies(conclusion as IConvertible, premise as IConvertible); …Run Code Online (Sandbox Code Playgroud)我有一个基类:
public abstract class DomainEventSubscriber<T> where T : DomainEvent
{
public abstract void HandleEvent(T domainEvent);
public Type SubscribedToEventType() { return typeof(T); }
}
Run Code Online (Sandbox Code Playgroud)
还有一个存储DomainEventSubscriber引用的类:
public class DomainEventPublisher
{
private List<DomainEventSubscriber<DomainEvent>> subscribers;
public void Subscribe<T>(DomainEventSubscriber<T> subscriber)
where T : DomainEvent
{
DomainEventSubscriber<DomainEvent> eventSubscriber;
eventSubscriber = (DomainEventSubscriber<DomainEvent>)subscriber;
if (!this.Publishing)
{
this.subscribers.Add(eventSubscriber);
}
}
}
Run Code Online (Sandbox Code Playgroud)
即使Subscribe方法类型受到限制,我也无法转换DomainEventSubscriber<T> subscriber where T : DomainEvent为DomainEventSubscriber<DomainEvent>:
eventSubscriber = (DomainEventSubscriber<DomainEvent>)subscriber;
Run Code Online (Sandbox Code Playgroud)
我将如何进行这种转换,或者我是否为一个令人讨厌的代码味道做好准备?
我有一个字符串数组,我想在中心的某处添加一个新值,但不知道如何执行此操作.任何人都可以为我制作这种方法吗?
void AddValueToArray(String ValueToAdd, String AddAfter, ref String[] theArray) {
// Make this Value the first value
if(String.IsNullOrEmpty(AddAfter)) {
theArray[0]=ValueToAdd; // WRONG: This replaces the first Val, want to Add a new String
return;
}
for(int i=0; i<theArray.Length; i++) {
if(theArray[i]==AddAfter) {
theArray[i++]=ValueToAdd; // WRONG: Again replaces, want to Add a new String
return;
}
}
}
Run Code Online (Sandbox Code Playgroud)