作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是一个多么棒的网站,多年来我一直潜伏在这里阅读其他人的问题,但现在我有了自己的问题。
我的同事写了一个非常像下面的类。我一看到它就知道它行不通,但我没有向他解释为什么它行不通。
他将其声明为 ControlItem<Button>
时所期望的就是用base调用Draw()时会调用Draw(Button)方法。相反,我们总是以抛出异常告终。
这是协方差问题吗?
public abstract class ControlItem
{
public ControlItem()
{
}
abstract public void Draw();
}
public class ControlItem<T> : ControlItem where T : Control, new()
{
public T MyControl { get; set; }
private ControlItem()
{ }
public ControlItem(T control)
: base()
{
MyControl = control;
}
public override void Draw()
{
Draw(this.MyControl);
}
public void Draw(Control cntrl)
{
throw new NotImplementedException();
}
public void Draw(Button button)
{
//Do some work
}
}
最佳答案
Is this a covariance issue?
不,这是一个静态与动态调度问题。静态分派(dispatch)意味着重载方法调用在编译时根据传入的变量类型绑定(bind)到适当的类型:
class Base { }
class Derived : Base { }
class Foo
{
void Test()
{
Base a = new Base();
Overload(a); // prints "base"
Derived b = new Derived();
Overload(b); // prints "derived"
// dispatched based on c's declared type!
Base c = new Derived();
Overload(c); // prints "base"
}
void Overload(Base obj) { Console.WriteLine("base"); }
void Overload(Derived obj) { Console.WriteLine("derived"); }
}
动态调度意味着函数在运行时根据存储在变量中的对象的实际类型进行绑定(bind):
class Base
{
public virtual void Override() { Console.WriteLine("base"); }
}
class Derived : Base
{
public override void Override() { Console.WriteLine("derived"); }
}
class Foo
{
void Test()
{
Base a = new Base();
a.Override(); // prints "base"
Derived b = new Derived();
b.Override(); // prints "derived"
// dynamically dispatched based type of object stored in c!
Base c = new Derived();
c.Override(); // prints "derived"
}
void Overload(Base obj) { Console.WriteLine("base"); }
void Overload(Derived obj) { Console.WriteLine("derived"); }
}
最后的打印显示了两者之间的区别。与大多数基于类的 OOP 语言一样,C# 仅支持 this
隐式参数的动态调度(称为“单一调度”)。换句话说,重写 方法是动态调度的,但重载方法不是。
在单一调度语言中伪造多重调度的典型解决方案是使用 visitor pattern ,在这里对您有用。
关于c# - 使用泛型将其声明为 Button 但被视为类内部的 Control。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/730561/
我是一名优秀的程序员,十分优秀!