C# 我不知道';我不太懂C语言#
为什么当我使用C# 我不知道';我不太懂C语言#,c#,C#,为什么当我使用objA.Rename()时,它实际上使用了在类B中编写的覆盖版本。到底什么是objA。如果是,那么为什么使用覆盖版本。如果是B,那么为什么objA.name不是bbb 对象永远不会改变。在内存中,它始终是aB,无论您选择如何与它交互。了解这种情况的方法是对变量调用.GetType(),它们都会告诉您每个变量都是B的一个实例 Class A { string name = "a"; public virtual void Rename(){//rename nam
objA.Rename()
时,它实际上使用了在类B中编写的覆盖版本。到底什么是objA
。如果是,那么为什么使用覆盖版本。如果是B,那么为什么objA.name
不是bbb 对象永远不会改变。在内存中,它始终是aB
,无论您选择如何与它交互。了解这种情况的方法是对变量调用.GetType()
,它们都会告诉您每个变量都是B
的一个实例
Class A
{
string name = "a";
public virtual void Rename(){//rename name to aaa}
}
Class B:A
{
string name = "b";
public override void Rename(){//rename name to bbb}
}
void Main()
{
B objB = new B();
A objA = objB as A;
print(objB.name);// b
print(objA.name);// a
objA.Rename();
print(objB.name);// bbb
print(objA.name);// a
}
最后得到“a”
的原因是,您有两个不同的名称声明。意思:A.name
与B.name
要解决此问题,您只需删除string name=“b”代码>来自B
并改为放置name=“B”将>编码到它的构造函数中
B objB = new B();
A objA = objB as A;
Console.WriteLine(objB.GetType()) // B
Console.WriteLine(objA.GetType()) // B
考虑这一点的另一种方式是,如果您在B
内部调用base.name
,我相信您将得到与“a”
相同的结果,向您显示B
实际上有两个独立的name
声明,首先,你必须明白,c#中的casting是一个用于非常不同转换的名称,可能会造成混淆
您所询问的角色从技术上讲被称为参考转换。引用转换是保持身份的转换,这意味着对象不会更改,更改的是引用的类型:
Class A
{
string name = "a";
public virtual void Rename(){//rename name to aaa}
}
Class B:A
{
public override void Rename(){//rename name to bbb}
public B() { name = "b"; }
}
这里,s
和o
引用了完全相同的对象,唯一改变的是引用的类型
需要注意的是,引用转换是由编译器自动提供的,您不能定义用户定义的保留身份的转换,您将得到一个编译器错误
您将遇到的最常见的引用转换是什么?类型与子类型或类型与实现的接口等之间的任何转换
现在考虑下面看似相似的代码:
var s = “Hello”;
var o = (object)s;
var b = ReferenceEquals(s, o); //returns true
这段代码与前一段代码完全不同。为什么?因为这里的强制转换不是引用转换。这实际上调用了在System.Int32
中实现的用户定义的explicit
cast运算符i
和l
是不同的对象
c#中另一个重要的转换是装箱和拆箱转换。它们不具有身份保护功能,但它们具有共同的“特性”,无法实现用户定义的装箱或拆箱转换。装箱是指将值类型转换为与赋值兼容的引用类型,而取消装箱则是相反的操作:
var l = 1L;
var i = (int)l;
您如何第一眼就知道它是否是引用转换?好吧,只要你知道所涉及类型的层次结构。接口等。您应该能够对其进行推理。如果我执行类似于类A{string aName=“A”;}类B:A{string bName=“B”;}B objB=new B(),则可能重复添加到我的问题中;A objA=作为A的objB;那么,如果对象总是相同的,为什么objA没有bName的定义?@HaoyuLi,因为引用的类型是a
,而a
类型不知道B
类型的任何具体实现。同样,不要混淆对象的类型和引用的类型,它们不是同一件事。@HaoyuLi对象本身在内存中总是aB
,但这并不意味着它在与它交互的方式中总是aB
。在您的情况下,通过强制转换它,您选择与它交互,就像它是一个A
,但在幕后它实际上是一个B
。我明白了,但我们什么时候需要转换引用类型?如果对象不变,为什么不直接使用该对象呢?为什么我们需要或者想要把它作为另一种参考类型?@HaoyuLi想象你有一种知道如何喂养任何动物的方法,你想把它称为猫、狗和大象。你真的想为你可能拥有的每一只动物反复地写一个基本相同的方法吗?还是只为基本类型动物写一个方法更容易?引用转换是多态性的核心,多态性是任何面向对象语言的基本特性和工具。一路上我会多练习,多学习。
var i = 1;
var o = (object)i; //boxing
var ii = (int)o; //unboxing