Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 调用类外的giraffe.Eat(apple),重构它使其位于类内,然后突然可以观察到行为的变化_C#_Generics_Overload Resolution - Fatal编程技术网

C# 调用类外的giraffe.Eat(apple),重构它使其位于类内,然后突然可以观察到行为的变化

C# 调用类外的giraffe.Eat(apple),重构它使其位于类内,然后突然可以观察到行为的变化,c#,generics,overload-resolution,C#,Generics,Overload Resolution,或者,你可能会说,嘿,我意识到我的Giraffe逻辑实际上足够通用,可以移动到基类,但不能移动到Animal,所以我将重构我的Giraffe代码,以: class Mammal : Animal { public void Eat(Food f) { ... } public override void Eat(Apple a) { ... } } class Giraffe : Mammal { ... } 现在所有对giraffe.Eat(apple)insidegiraf

或者,你可能会说,嘿,我意识到我的Giraffe逻辑实际上足够通用,可以移动到基类,但不能移动到Animal,所以我将重构我的
Giraffe
代码,以:

class Mammal : Animal 
{
  public void Eat(Food f) { ... } 
  public override void Eat(Apple a) { ... }
}
class Giraffe : Mammal
{
  ...
}
现在所有对
giraffe.Eat(apple)
inside
giraffe
的调用在重构后突然有了不同的重载解析行为?那将是非常出乎意料的

C#是一种成功的语言;我们非常希望确保简单的重构,比如改变层次结构中方法被覆盖的位置,不会导致行为上的细微变化

总结:

  • 重载解析将接收器优先于其他参数,因为调用了解接收器内部的专用代码比调用不了解接收器内部的通用代码要好
  • 重载解析期间,是否以及在何处重写方法未被考虑;所有方法都被视为从未为了重载解析而重写过。这是一个实现细节,而不是类型表面的一部分
  • 解决了重载解析问题——当然是模可访问性!——无论代码中的问题发生在何处,都是这样。我们并没有一种算法用于解析接收方是包含代码类型的情况,也并没有另一种算法用于解析调用在不同类中的情况

关于相关问题的其他想法可以在这里找到:这里

并不确定确定确定方法分辨率的规范,但暂时的解决方法是
((Executor)this)。Execute((string)item)
。。这太难看了。根据最具体的情况,应该选择重载。@Steve,这与这里介绍的情况不同,因为这不涉及重载,而C#spec专门以不同的方式处理这种特殊情况。@DavidL似乎是这样。我不知道,非常有趣。事实上,它与泛型基类没有任何关系。我可以在没有代码的情况下重新编程。这让我非常惊讶。正确,在这种情况下,泛型参数是一个危险因素。@马克:有一些方法可以构造重载解析问题,其中泛型或泛型缺失被用作断开联系的因素,但这不是其中之一。例如,给定
类C{void M(int){}void M(T){}
并调用
C.M(123)
,非泛型将获胜。还有比这更微妙的决胜局;详细信息请参见规范。当然,我的后续问题是:为什么?我确信有一个很好的理由,但这对我来说似乎是一个令人惊讶的行为。@Mark Jon Skeet描述了原因,“这样做的原因是为了降低脆弱基类问题的风险,在基类中引入新方法可能会给派生自它的类的使用者带来问题。”@khargoosh Skeet的解释处理了一个不同的问题(为什么父类中的方法被忽略,即使它更适合)。脆性基类问题显然不适用于这里,因为我们处理的是添加到子类而不是基类的函数。改变行为也可以考虑在同一个类中重写方法,当将方法添加到基类中时,不会改变行为(这是脆弱的基类问题处理的)。乔恩实际上继续并指出这里所提到的问题,但不提及任何原因并调用该行为。“特别令人惊讶”他自己。@Voo:这可能是令人惊讶的,但也是故意的。看我的答案。
class Animal
{
  public virtual void Eat(Apple a) { ... }
}
class Giraffe : Animal
{
  public void Eat(Food f) { ... }
  public override void Eat(Apple a) { ... }
}
class Mammal : Animal 
{
  public void Eat(Food f) { ... } 
  public override void Eat(Apple a) { ... }
}
class Giraffe : Mammal
{
  ...
}