相关疑难解决方法(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
查看次数

当另一个接口设置为仅时,为什么属性被认为是不明确的?

在以下代码中:

interface IGet { int Value { get; } }

interface ISet { int Value { set; } }

interface IBoth : IGet, ISet { }

class Test
{
    public void Bla(IBoth a)
    {
        var x = a.Value; // Error: Ambiguity between 'IGet.Value' and 'ISet.Value'
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到一个错误:

'IGet.Value'和'ISet.Value'之间的歧义

为什么编译器无法确定访问的属性必须来自IGet

编辑 - 我猜测编译器首先尝试确定正在访问哪个属性,然后才检查它是get还是set.问题是 - 为什么?为什么不排除那些不提供吸气剂的候选人呢?为什么不解析实际的get/set方法并忽略它是属性的事实?

更新:使用方法而不是属性的更多代码,其中问题不存在.属性并不完全像一对方法.

c# compiler-errors

24
推荐指数
3
解决办法
1395
查看次数

如何将多个对象添加到单个阵列?

我正在为游戏设计一个非常简单的库存系统.我遇到了一个障碍,我有一个需要接受多种类型对象的库存(一个特定类型的数组).我的代码:

IWeapon[] inventory = new IWeapon[5];

public void initialiseInventory(IWeapon weapon, IArmour armour)
{
    inventory[0] = weapon; // Index 0 always contains the equipped weapon
    inventory[1] = armour; // Index 1 always contains the equipped armour
}
Run Code Online (Sandbox Code Playgroud)

我会得到一个错误,指出数组不能将装甲对象转换为武器对象(这是数组类型).然后我想我可以创建IWeapon和IArmour将继承的超类(嗯,界面准确).但后来又遇到了另一个错误......

IItem[] inventory = new IItem[5];

public void initialiseInventory(IWeapon weapon, IArmour armour)
{
    inventory[0] = weapon; // Index 0 always contains the equipped weapon
    inventory[1] = armour; // Index 1 always contains the equipped armour

    Console.WriteLine("The weapon name is: " + inventory[0].Name) // Problem! …
Run Code Online (Sandbox Code Playgroud)

c# arrays object

4
推荐指数
1
解决办法
1697
查看次数

这有什么神奇之处?

我最近发现臭名昭着的Jon Skeet关于使用LINQ to XML的帖子.这段特殊代码引起了我的注意:

// Customers is a List<Customer>
XElement customersElement = new XElement("customers",
    customers.Select(c => new XElement("customer", //This line is "magic"
        new XAttribute("name", c.Name),
        new XAttribute("lastSeen", c.LastOrder)
        new XElement("address",
            new XAttribute("town", c.Town),
            new XAttribute("firstline", c.Address1),
            // etc
    ));
Run Code Online (Sandbox Code Playgroud)

我决定在我的应用程序中自己测试它,我有一个foreach循环设置如下:

foreach (var kvp in m_jobs) {    //m_jobs is a Dictionary<string,Job>
    m_xmlDoc.Root.Element("SCHED_TABLE").Add(
        kvp.Value.GenerateXmlNode())
    );
}
Run Code Online (Sandbox Code Playgroud)

我修改为:

m_xmlDoc.Root.Element("SCHED_TABLE").Add(
    m_jobs.Select(job => job.Value.GenerateXmlNode())
};
Run Code Online (Sandbox Code Playgroud)

其中GenerateXmlNode()是为特定作业项生成适当XML标记的方法.我不确定会发生什么,但是它看起来和我的foreach循环完全一样.我不太明白的是为什么?!此外,这被认为是LINQ的"滥用"还是"功能"?

为清晰起见编辑:我知道.Select将返回一个IEnumerable,其中包含我要求的内容,但我并没有明确地枚举它.我理解.Add是如何工作的,因为它接受了可变数量的参数,但同样,我没有明确枚举传递这些参数.那么......它怎么还能用呢?

c# xml linq

4
推荐指数
2
解决办法
394
查看次数

一个实现两个不同IObservable的类?

我有两个事件类,叫他们StatusChangedValueChanged.我想知道将这些'流'暴露为IObservable.正在实施IObservable<Status>IObservable<Value>在同一个班级'坏'?是否可能导致我(或我班级的用户)悲伤?

c# system.reactive

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