值类型何时包含引用类型?

P.B*_*key 17 c# value-type reference-type

我理解,在引用类型上使用值类型的决定应该基于语义,而不是性能.我不明白为什么值类型可以合法地包含引用类型成员?这有几个原因:

首先,我们不应该构建一个需要构造函数的结构.

public struct MyStruct
{
    public Person p;
    // public Person p = new Person(); // error: cannot have instance field initializers in structs

    MyStruct(Person p)
    {
        p = new Person();
    }
}
Run Code Online (Sandbox Code Playgroud)

其次,由于值类型语义:

MyStruct someVariable;
someVariable.p.Age = 2; // NullReferenceException
Run Code Online (Sandbox Code Playgroud)

编译器不允许我Person在声明中初始化.我必须把它移到构造函数,依赖调用者,或期望一个NullReferenceException.这些情况都不是理想的.

.NET Framework是否在值类型中有任何引用类型的示例?我们什么时候应该这样做(如果有的话)?

Mar*_*ell 20

值类型的实例永远不会包含引用类型的实例.引用类型对象位于托管堆上的某个位置,值类型对象可以包含对该对象的引用.这样的参考具有固定的大小.这样做很常见 - 例如每次在结构中使用字符串时.

但是,是的,您无法保证a中引用类型字段的初始化,struct因为您无法定义无参数构造函数(如果您使用C#以外的语言定义它,也无法保证它会被调用).

你说你应该"不构建一个struct需要构造函数".我说不然.由于值类型几乎总是不可变的,因此必须使用构造函数(很可能通过工厂到私有构造函数).否则它将永远不会有任何有趣的内容.

使用构造函数.构造函数很好.

如果您不想传入Person初始化的实例p,则可以通过属性使用延迟初始化.(因为显然公共场地p只是为了示范,对吧?对吗?)

public struct MyStruct
{
    public MyStruct(Person p)
    {
        this.p = p;
    }

    private Person p;

    public Person Person
    {
        get
        {
            if (p == null)
            {
                p = new Person(…); // see comment below about struct immutability
            }
            return p;
        }
    }

    // ^ in most other cases, this would be a typical use case for Lazy<T>;
    //   but due to structs' default constructor, we *always* need the null check.
}
Run Code Online (Sandbox Code Playgroud)