代表家庭和人民

本文关键字:家庭 | 更新日期: 2023-09-27 18:13:54

在c++中我可以这样做

class Person
{
    House * myhouse;
}
class House
{
    std::vector<Person*> members;
}

如何在c#中做类似的事情?

代表家庭和人民

public class Person
{
    public House MyHouse { get; set; }
}
public class House
{
    public List<Person> Members { get; private set; }
    public House()
    {
        this.Members = new List<Person>();
    }
}

这里我使用属性,特别是自动属性,而不是字段。这既是为了更干净,将字段公开给外部世界通常不如公开属性干净,也是因为我可以通过这种方式控制人们如何访问属性进行读和写。在这个例子中,属性Members对于读是公有的,但是对于写是私有的,我在构造函数中初始化了它。

在c#中没有对象在堆栈中分配的概念,对象总是在堆中分配的。

这意味着类总是引用类型,并且List类型的变量是对List类型对象的引用,就像c++中的指针一样。因此,您需要使用new操作符来分配它,否则默认值将为null。

当然,正如你所知道的,在c#中有垃圾收集器,所以你不需要删除对象。

c#中也有值类型,像int、float、double和struct这样的基本类型都是值类型,它们的工作方式确实不同。

数组和字符串仍然是引用类型(类)。

还需要注意的是,c#类的字段在构造函数中默认初始化为0,你能想到的每种类型都将初始化为0,因此,指针将为null,浮点数将为0.0f,结构体将是所有字段设置为0的结构体。就像c中的callloc。

然而,还有另一种完全不同的方法。我们可以使用基类Collection,并使MyHouse属性完全透明和安全:我们在更改集合时设置它,这种技术经常使用。
    public class Person
    {
        // This field is internal, it means that all classes in the same module (in the same dll for example) can access to this field.
        // This keyword was introduced for the same reason that the "friend" keyword exists in C++.
        // We need this internal so we can modify it from House class.
        internal House house;
        public House MyHouse
        {
            get { return this.house; }
        }
    }
    public class House :
        System.Collections.ObjectModel.Collection<Person>
    {
        // We shadow the base member, this is faster than default implementation, O(1).
        public new bool Contains(Person person)
        {
            return person != null && person.house == this;
        }
        protected override void RemoveItem(int index)
        {
            Person person = this[index];
            base.RemoveItem(index);
            person.house = null;
        }
        protected override void SetItem(int index, Person item)
        {
            if (item == null)
                throw new ArgumentNullException("Person is null");
            if (item.house != null)
                throw new InvalidOperationException("Person already owned by another house");
            Person old = this[index];
            base.SetItem(index, item);
            old.house = null;
            item.house = this;
        }
        protected override void InsertItem(int index, Person item)
        {
            if (item == null)
                throw new ArgumentNullException("Person is null");
            if (item.house != null)
                throw new InvalidOperationException("Person already owned by another house");
            base.InsertItem(index, item);
            item.house = this;
        }
        protected override void ClearItems()
        {
            foreach (Person person in this)
            {
                person.house = null;
            }
            base.ClearItems();
        }
    }
class Person
{
    House myhouse;
}
class House
{
    List<Person> members = new List<Person>;
}