简体   繁体   English

你能在一个结构中有一个类吗?

[英]Can you have a class in a struct?

Is it possible in C# to have a Struct with a member variable which is a Class type? 在C#中是否可以使用具有类型类型的成员变量的Struct? If so, where does the information get stored, on the Stack, the Heap, or both? 如果是这样,信息存储在哪里,堆栈,堆,或两者?

Yes, you can. 是的你可以。 The pointer to the class member variable is stored on the stack with the rest of the struct's values, and the class instance's data is stored on the heap. 指向类成员变量 的指针 与结构的其余值一起存储 在堆栈中 ,类实例的数据存储在堆上。

Structs can also contain class definitions as members (inner classes). 结构也可以包含类定义作为成员(内部类)。

Here's some really useless code that at least compiles and runs to show that it's possible: 这是一些真正无用的代码,至少编译并运行以显示它是可能的:

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MyStr m = new MyStr();
            m.Foo();

            MyStr.MyStrInner mi = new MyStr.MyStrInner();
            mi.Bar();

            Console.ReadLine();
        }
    }

    public class Myclass
    {
        public int a;
    }

    struct MyStr
    {
        Myclass mc;

        public void Foo()
        {
            mc = new Myclass();
            mc.a = 1;
        }

        public class MyStrInner
        {
            string x = "abc";

            public string Bar()
            {
                return x;
            }
        }
    }
}

The class content gets stored on the heap. 类内容存储在堆上。

A reference to the class (which is almost the same as a pointer) gets stored with the struct content. 对类的引用(与指针几乎相同)与struct内容一起存储。 Where the struct content is stored depends on whether it's a local variable, method parameter, or member of a class, and whether it's been boxed or captured by a closure. 存储结构内容的位置取决于它是局部变量,方法参数还是类的成员,以及它是否被闭包装箱或捕获。

If one of the fields of a struct is a class type, that field will either hold the identity of a class object or else a null referece. 如果结构的某个字段是类类型,则该字段将保留类对象的标识 ,或者保留null引用。 If the class object in question is immutable (eg string ), storing its identity will effectively also store its contents. 如果所讨论的类对象是不可变的(例如string ),则存储其标识也将有效地存储其内容。 If the class object in question is mutable, however, storing the identity will be an effective means of storing the contents if and only if the reference will never fall into the hands of any code which might mutate it once it is stored in the field . 但是,如果所讨论的类对象是可变的,那么存储该标识将是一种有效的存储内容的方法, 当且仅当该引用永远不会落入任何代码的手中,这些代码一旦存储在字段中就可能使其变异

Generally, one should avoid storing mutable class types within a structure unless one of two situations applies: 通常,应避免在结构中存储可变类类型,除非以下两种情况之一适用:

  1. What one is interested in is, in fact, the identity of the class object rather than its content. 事实上,人们感兴趣的是类对象的身份而不是其内容。 For example, one might define a `FormerControlBounds` structure which holds fields of type `Control` and `Rectangle`, and represents the `Bounds` that control had at some moment in time, for the purpose of being able to later restore the control to its earlier position. 例如,可以定义一个`FormerControlBounds`结构,它保存“Control”和“Rectangle”类型的字段,并表示某个时刻控件具有的“Bounds”,以便以后能够恢复控件到它早先的位置。 The purpose of the `Control` field would not be to hold a copy of the control's state, but rather to identify the control whose position should be restored. “Control”字段的目的不是保存控件状态的副本,而是识别应该恢复其位置的控件。 Generally the struct should avoid accessing any mutable members of the object to which it holds a reference, except in cases where it is clear that such access is referring to the current mutable state of the object in question (eg in a `CaptureControlPosition` or `RestoreControlToCapturedPosition` method, or a `ControlHasMoved` property). 通常,struct应该避免访问它拥有引用的对象的任何可变成员,除非很明显这样的访问是指有关对象的当前可变状态(例如在`CaptureControlPosition`或` RestoreControlToCapturedPosition`方法,或`ControlHasMoved`属性)。
  2. The field is `private`, the only methods which read it do so for the purpose of examining its properties without exposing the object itself it to outside code, and the only methods which write it will create a new object, perform all of the mutations that are ever going to happen to it, and then store a reference to that object. 该字段是`private`,唯一读取它的方法是为了检查其属性而不将对象本身暴露给外部代码,并且编写它的唯一方法将创建一个新对象,执行所有突变它将永远发生在它上面,然后存储对该对象的引用。 One could, for example, design a `struct` which behaved much like an array, but with value semantics, by having the struct hold an array in a private field, and by having every attempt to write the array create a new array with data from the old one, modify the new array, and store the modified array to that field. 例如,人们可以设计一个`struct`,它的行为很像一个数组,但具有值语义,通过让struct在私有字段中保存一个数组,并且每次尝试编写数组都会创建一个包含数据的新数组从旧的数组中,修改新数组,并将修改后的数组存储到该字段。 Note that even though the array itself would be a mutable type, every array instance that would ever be stored in the field would be effectively immutable, since it would never be accessible by any code that might mutate it. 请注意,即使数组本身是一个可变类型,每个存储在字段中的数组实例都是有效的不可变的,因为任何可能会使其变异的代码都无法访问它。

Note that scenario #1 is pretty common with generic types; 请注意,场景#1在泛型类型中非常常见; for example, it's very common to have a dictionary whose "values" are the identities of mutable objects; 例如,有一个字典的“值”是可变对象的身份是很常见的; enumerating that dictionary will return instances of KeyValuePair whose Value field holds that mutable type. 枚举该字典将返回KeyValuePair的实例,其Value字段包含该可变类型。

Scenario #2 is less common. 场景#2不太常见。 There is alas no way to tell the compiler that struct methods other than property setters will modify a struct and their use should thus be forbidden in read-only contexts; 没有办法告诉编译器除了属性设置器之外的结构方法将修改结构,因此在只读上下文中应禁止它们的使用; one could have a struct that behaved like a List<T> , but with value semantics, and included an Add method, but an attempt to call Add on a read-only struct instance would generate bogus code rather than a compiler error. 一个可以有一个行为类似于List<T> ,但是具有值语义,并且包含一个Add方法,但是尝试在只读结构实例上调用Add会产生伪代码而不是编译器错误。 Further, mutating methods and property setters on such structs will generally perform rather poorly. 此外,这种结构上的变异方法和属性设定器通常表现得相当差。 Such structs can be useful are when they exist as an immutable wrapper on an otherwise-mutable class; 当这些结构作为一个不可变的包装器存在于其他可变类中时,它们可能是有用的; if such a struct is never boxed, performance will often be better than a class. 如果这样的结构永远不会被装箱,那么性能往往比一个类好。 If boxed exactly once (eg by being cast to an interface type), performance will generally be comparable to a class. 如果只装箱一次(例如通过铸造到接口类型),性能通常可以与一个类别相比。 If boxed repeatedly, performance can be much worse than a class. 如果重复加框,性能可能比一类差。

It's probably not a recommended practice to do so: see http://msdn.microsoft.com/en-us/library/ms229017(VS.85).aspx 这可能不是推荐的做法:请参阅http://msdn.microsoft.com/en-us/library/ms229017(VS.85).aspx

Reference types are allocated on the heap, and memory management is handled by the garbage collector. 引用类型在堆上分配,内存管理由垃圾收集器处理。

Value types are allocated on the stack or inline and are deallocated when they go out of scope. 值类型在堆栈或内联中分配,并在超出范围时释放。

In general, value types are cheaper to allocate and deallocate. 通常,值类型分配和释放更便宜。 However, if they are used in scenarios that require a significant amount of boxing and unboxing, they perform poorly as compared to reference types. 但是,如果它们用于需要大量装箱和拆箱的场景,则与参考类型相比,它们的性能很差。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 您可以在 c# 中的只读结构上设置默认参数吗? - Can you have default parameters on a readonly struct in c#? 你能覆盖一个类/结构的 Swagger 格式吗 - Can you override Swagger's format for a class / struct 你有一个依赖于类的接口吗? - Can you have an interface be dependent on a class? 在结构体中有一个类可以吗? - Is it ok to have a class inside a struct? 为什么不能在 C# 中声明静态结构,但它们可以有静态方法? - Why can't you declare a static struct in C#, but they can have static methods? 在C#中,如何拥有全局泛型类? - In C#, how can you have a global generic class? 如果您无法控制 class,您如何模拟 class 中的方法? - How can you mock the methods from a class if you have no control over the class? 有没有办法可以防止 struct 被实例化,或者我可以有一个将被复制的类? - Is there a way I can prevent struct from being insantiated or can I have a class that will be copied? C#债券:我的债券结构中可以有自定义类的列表吗? - C# Bond: Can I have List of custom class in my bond struct? 如何在C#中的类内部为结构提供不同的保护级别? - How can I have different protection levels for a struct inside a class in C#?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM