c# - 家庭和人民的代表

标签 c# data-structures

在 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 对读是公共(public)的,对写是私有(private)的,我在构造函数中对其进行了初始化。

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

这意味着类总是引用类型,List 类型的变量是对 List 类型对象的引用,就像 C++ 中的指针一样。 为此需要使用new运算符来分配,否则默认值为null。

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

在 C# 中也有值类型,基本类型如 int、float、double 和 struct 都是值类型,它们确实以不同的方式工作。

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

另请注意,在 C# 中,类字段在构造函数中默认初始化为 0,您可以想到的每种类型都将初始化为 0,因此,指针将为 null, float 将为 0.0f,结构体将为是一个所有字段都设置为 0 的结构。就像 C 中的 calloc。

然而,还有另一种完全不同的方法。 我们可以使用基类 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();
        }
    }

关于c# - 家庭和人民的代表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8050523/

相关文章:

javascript - javascript中数组交集的最简单代码

c# - 按类的字符串字段对列表进行排序

c# - 如何在自己的客户端-服务器应用程序中使用 System.IdentityModel

c# - 如何将响应行为添加到 asp :GridView

c# - 如何添加到特定 ListView 列

python - 200k字符串相互比较的数据结构

javascript - 每个簇选取 m 个点

java - 实现多列表的最有效方法?

java文件输入数字对链表

c# - IdentiyServer 颁发的 Jwt token 如何在 Web Api 应用程序中验证