在基本类型“virtual”中声明一个方法,然后在子类型中使用“override”关键字重写它,与在子类型中声明匹配的方法时简单地使用“new”关键字相比,两者之间有什么区别?
当前回答
我总是觉得这样的事情用图片更容易理解:
再一次,用joseph daigle的密码,
public class Foo
{
public /*virtual*/ bool DoSomething() { return false; }
}
public class Bar : Foo
{
public /*override or new*/ bool DoSomething() { return true; }
}
如果你像这样调用代码:
Foo a = new Bar();
a.DoSomething();
注意:重要的是,我们的对象实际上是一个Bar,但我们将它存储在类型为Foo的变量中(这类似于强制转换它)。
那么结果将如下所示,这取决于您在声明类时使用的是virtual/override还是new。
其他回答
我的解释来自于使用属性来帮助理解差异。
重写很简单,对吧?底层类型覆盖父类型。
新可能是误导(对我来说是)。使用属性更容易理解:
public class Foo
{
public bool GetSomething => false;
}
public class Bar : Foo
{
public new bool GetSomething => true;
}
public static void Main(string[] args)
{
Foo foo = new Bar();
Console.WriteLine(foo.GetSomething);
Bar bar = new Bar();
Console.WriteLine(bar.GetSomething);
}
使用调试器,你可以注意到Foo Foo有两个GetSomething属性,因为它实际上有两个版本的属性,Foo's和Bar's,为了知道使用哪个,c#“选择”当前类型的属性。
如果你想使用Bar的版本,你应该使用override或使用Foo Foo代替。
Bar Bar只有1,因为它想要GetSomething的全新行为。
我总是觉得这样的事情用图片更容易理解:
再一次,用joseph daigle的密码,
public class Foo
{
public /*virtual*/ bool DoSomething() { return false; }
}
public class Bar : Foo
{
public /*override or new*/ bool DoSomething() { return true; }
}
如果你像这样调用代码:
Foo a = new Bar();
a.DoSomething();
注意:重要的是,我们的对象实际上是一个Bar,但我们将它存储在类型为Foo的变量中(这类似于强制转换它)。
那么结果将如下所示,这取决于您在声明类时使用的是virtual/override还是new。
下面是一些代码来理解虚拟方法和非虚拟方法行为的区别:
class A
{
public void foo()
{
Console.WriteLine("A::foo()");
}
public virtual void bar()
{
Console.WriteLine("A::bar()");
}
}
class B : A
{
public new void foo()
{
Console.WriteLine("B::foo()");
}
public override void bar()
{
Console.WriteLine("B::bar()");
}
}
class Program
{
static int Main(string[] args)
{
B b = new B();
A a = b;
a.foo(); // Prints A::foo
b.foo(); // Prints B::foo
a.bar(); // Prints B::bar
b.bar(); // Prints B::bar
return 0;
}
}
new关键字用于隐藏。-意味着你在运行时隐藏你的方法。输出将基于基类方法。 Override用于重写。-表示您正在调用派生类方法引用基类。输出将基于派生类方法。
new关键字实际上创建了一个全新的成员,该成员只存在于该特定类型上。
例如
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
该方法存在于这两种类型上。当您使用反射并获取Bar类型的成员时,您实际上会发现两个称为DoSomething()的方法看起来完全相同。通过使用new,你可以有效地将实现隐藏在基类中,这样当类从Bar派生出来时(在我的例子中),对base. dosomething()的方法调用就会到Bar而不是Foo。
推荐文章
- 我如何使一个方法的返回类型泛型?
- 何时处理CancellationTokenSource?
- 如何获取正在执行的程序集版本?
- AutoMapper vs valueinjector
- 为什么控制台不。Writeline,控制台。在Visual Studio Express中编写工作?
- 什么是.NET程序集?
- 字符串不能识别为有效的日期时间“格式dd/MM/yyyy”
- 函数应该返回空对象还是空对象?
- 如何转换日期时间?将日期时间
- 如何在c#中连接列表?
- 在c#中引用类型变量的“ref”的用途是什么?
- 防止在ASP中缓存。NET MVC中使用属性的特定操作
- 转换为值类型'Int32'失败,因为物化值为空
- c#中有任何连接字符串解析器吗?
- JavaScript: override alert()