相关疑难解决方法(0)

当逆变导致模糊时,没有警告或错误(或运行时故障)

首先,请记住.NET StringIConvertibleICloneable.

现在,考虑以下非常简单的代码:

//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先生很久以前就做过这样的事情.在他博客的评论中,几乎每个人都认为这应该是一个错误.然而他们默默地允许这样做. …

.net c# ambiguity contravariance undefined-behavior

43
推荐指数
2
解决办法
917
查看次数

如何找到两种类型中最小的可分配类型(重复)?

这是两种使用的扩展方法

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仅限使用,除非没有其他方法.

有没有好的方法之间找到共同类型的最适合type1type2

或者有更好的事情来实现这一目标吗?


更新:

根据我个人的理解,由于能够使用类实现多个接口, …

c# reflection types

13
推荐指数
1
解决办法
2097
查看次数

非正式的谬误导致堆栈溢出

  • 破碎的代码

    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)

c# language-agnostic logic

9
推荐指数
1
解决办法
600
查看次数

转换泛型参数与'where'类型约束不可能?

我有一个基类:

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 : DomainEventDomainEventSubscriber<DomainEvent>:

eventSubscriber = (DomainEventSubscriber<DomainEvent>)subscriber;
Run Code Online (Sandbox Code Playgroud)

我将如何进行这种转换,或者我是否为一个令人讨厌的代码味道做好准备?

c# generics

7
推荐指数
1
解决办法
401
查看次数

如何在数组中插入值,保留顺序?

我有一个字符串数组,我想在中心的某处添加一个新值,但不知道如何执行此操作.任何人都可以为我制作这种方法吗?

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)

c# arrays

2
推荐指数
1
解决办法
6432
查看次数