這里的“切片”是指 C 對該術語的使用。供參考: 什么是物件切片?
我在以下情況下考慮了這一點:
我有這個人:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name)
{
Name = name;
}
public override string ToString()
{
return Name;
}
public virtual void Greet()
{
Console.WriteLine("Hello!");
}
}
}
老師
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Teacher : Person
{
public Teacher() : base("empty")
{
}
public override void Greet()
{
base.Greet();
Console.WriteLine("I'm a teacher");
}
}
}
學生
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Student : Person
{
public Student() : base("empty")
{
}
public override void Greet()
{
base.Greet();
Console.WriteLine("I'm a student!");
}
}
}
和主要
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Student s = new Student();
Teacher t = new Teacher();
List<Person> persoane = new List<Person>();
persoane.Add(s);
persoane.Add(t);
foreach(Person person in persoane)
{
person.Greet();
}
}
}
}
我希望看到“你好!” 在螢屏上出現兩次(因為這個切片概念)但我得到了你好!我是學生,你好!我是一名教師。
根據 MS Docs,這是一個隱式轉換。但是在 C 中,由于物件切片,我非常確定我會得到“你好!” 兩次。
所以,我的問題是:C# 有切片嗎?另外,如果我想使用 Student 和 Teacher 作為一個人,我會怎么做?(不改變類,只有主要)
謝謝!
uj5u.com熱心網友回復:
new您可以通過應用關鍵字而不是方法來實作類似的效果override,但它不像在 C 中那樣對物件進行切片:
Person p = new Person();
p.Greet();
Student s = new Student();
s.Greet();
Person ps = s;
ps.Greet();
Student s2 = (Student)ps;
s2.Greet();
class Person
{
public virtual void Greet()
{
Console.WriteLine("Hello!");
}
}
class Student : Person
{
new public void Greet() // note new here
{
Console.WriteLine("I'm a student!");
}
}
輸出:
Hello! // from Person
I'm a student! // from Student
Hello! // from Student assigned to Person
I'm a student! // from Student as Person casted back to Student
它是如何作業的?
首先我強調我們使用new修飾符來顯式地隱藏一個方法。如果你不使用它,它會生成一個編譯器警告。接下來,成員查找在 C# 中嚴格定義并考慮隱藏方法。
結果我們在 IL 代碼中看到的是編譯器會生成不同的方法呼叫:
IL_0008: callvirt instance void xxx.Person::Greet()
...
IL_0015: callvirt instance void xxx.Student::Greet()
...
IL_001e: callvirt instance void xxx.Person::Greet()
...
IL_002c: callvirt instance void xxx.Student::Greet()
但在除錯器中,我們看到有 4 個區域變數,但只有兩個物件:
0:000> !clrstack -a
...
010ff1b8 017f0929 xxx.Program.Main(System.String[]) [C:\...\Program.cs @ 22]
PARAMETERS:
args (0x010ff1d4) = 0x031a2420
LOCALS:
0x010ff1d0 = 0x031a244c // p
0x010ff1cc = 0x031a41a8 // s
0x010ff1c8 = 0x031a41a8 // ps
0x010ff1c4 = 0x031a41a8 // s2
這是為什么?C# 中的每個物件都帶有其型別資訊。那東西稱為方法表(MT),基本上是一些型別唯一的指標大小。您不能將該數字切成有意義的較小部分。
I have not understood all the details about the method table and related stuff yet.
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/424800.html
下一篇:如何將嵌套陣串列示為一維陣列?
