What's the difference between struct and class in .NET?

前端 未结 19 1399
一向
一向 2020-11-22 01:51

What\'s the difference between struct and class in .NET?

相关标签:
19条回答
  • 2020-11-22 01:57

    In .NET, there are two categories of types, reference types and value types.

    Structs are value types and classes are reference types.

    The general difference is that a reference type lives on the heap, and a value type lives inline, that is, wherever it is your variable or field is defined.

    A variable containing a value type contains the entire value type value. For a struct, that means that the variable contains the entire struct, with all its fields.

    A variable containing a reference type contains a pointer, or a reference to somewhere else in memory where the actual value resides.

    This has one benefit, to begin with:

    • value types always contains a value
    • reference types can contain a null-reference, meaning that they don't refer to anything at all at the moment

    Internally, reference types are implemented as pointers, and knowing that, and knowing how variable assignment works, there are other behavioral patterns:

    • copying the contents of a value type variable into another variable, copies the entire contents into the new variable, making the two distinct. In other words, after the copy, changes to one won't affect the other
    • copying the contents of a reference type variable into another variable, copies the reference, which means you now have two references to the same somewhere else storage of the actual data. In other words, after the copy, changing the data in one reference will appear to affect the other as well, but only because you're really just looking at the same data both places

    When you declare variables or fields, here's how the two types differ:

    • variable: value type lives on the stack, reference type lives on the stack as a pointer to somewhere in heap memory where the actual memory lives (though note Eric Lipperts article series: The Stack Is An Implementation Detail.)
    • class/struct-field: value type lives completely inside the type, reference type lives inside the type as a pointer to somewhere in heap memory where the actual memory lives.
    0 讨论(0)
  • 2020-11-22 01:57
    +------------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
    |                        |                                                Struct                                                |                                               Class                                               |
    +------------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
    | Type                   | Value-type                                                                                           | Reference-type                                                                                    |
    | Where                  | On stack / Inline in containing type                                                                 | On Heap                                                                                           |
    | Deallocation           | Stack unwinds / containing type gets deallocated                                                     | Garbage Collected                                                                                 |
    | Arrays                 | Inline, elements are the actual instances of the value type                                          | Out of line, elements are just references to instances of the reference type residing on the heap |
    | Aldel Cost             | Cheap allocation-deallocation                                                                        | Expensive allocation-deallocation                                                                 |
    | Memory usage           | Boxed when cast to a reference type or one of the interfaces they implement,                         | No boxing-unboxing                                                                                |
    |                        | Unboxed when cast back to value type                                                                 |                                                                                                   |
    |                        | (Negative impact because boxes are objects that are allocated on the heap and are garbage-collected) |                                                                                                   |
    | Assignments            | Copy entire data                                                                                     | Copy the reference                                                                                |
    | Change to an instance  | Does not affect any of its copies                                                                    | Affect all references pointing to the instance                                                    |
    | Mutability             | Should be immutable                                                                                  | Mutable                                                                                           |
    | Population             | In some situations                                                                                   | Majority of types in a framework should be classes                                                |
    | Lifetime               | Short-lived                                                                                          | Long-lived                                                                                        |
    | Destructor             | Cannot have                                                                                          | Can have                                                                                          |
    | Inheritance            | Only from an interface                                                                               | Full support                                                                                      |
    | Polymorphism           | No                                                                                                   | Yes                                                                                               |
    | Sealed                 | Yes                                                                                                  | When have sealed keyword                                                                          |
    | Constructor            | Can not have explicit parameterless constructors                                                     | Any constructor                                                                                   |
    | Null-assignments       | When marked with nullable question mark                                                              | Yes (+ When marked with nullable question mark in C# 8+)                                          |
    | Abstract               | No                                                                                                   | When have abstract keyword                                                                        |
    | Member Access Modifiers| public, private, internal                                                                            | public, protected, internal, protected internal, private protected                                |
    +------------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
    
    0 讨论(0)
  • 2020-11-22 02:00

    A short summary of each:

    Classes Only:

    • Can support inheritance
    • Are reference (pointer) types
    • The reference can be null
    • Have memory overhead per new instance

    Structs Only:

    • Cannot support inheritance
    • Are value types
    • Are passed by value (like integers)
    • Cannot have a null reference (unless Nullable is used)
    • Do not have a memory overhead per new instance - unless 'boxed'

    Both Classes and Structs:

    • Are compound data types typically used to contain a few variables that have some logical relationship
    • Can contain methods and events
    • Can support interfaces
    0 讨论(0)
  • 2020-11-22 02:02
    1. Events declared in a class have their += and -= access automatically locked via a lock(this) to make them thread safe (static events are locked on the typeof the class). Events declared in a struct do not have their += and -= access automatically locked. A lock(this) for a struct would not work since you can only lock on a reference type expression.

    2. Creating a struct instance cannot cause a garbage collection (unless the constructor directly or indirectly creates a reference type instance) whereas creating a reference type instance can cause garbage collection.

    3. A struct always has a built-in public default constructor.

      class DefaultConstructor
      {
          static void Eg()
          {
              Direct     yes = new   Direct(); // Always compiles OK
              InDirect maybe = new InDirect(); // Compiles if constructor exists and is accessible
              //...
          }
      }
      

      This means that a struct is always instantiable whereas a class might not be since all its constructors could be private.

      class NonInstantiable
      {
          private NonInstantiable() // OK
          {
          }
      }
      
      struct Direct
      {
          private Direct() // Compile-time error
          {
          }
      }
      
    4. A struct cannot have a destructor. A destructor is just an override of object.Finalize in disguise, and structs, being value types, are not subject to garbage collection.

      struct Direct
      {
          ~Direct() {} // Compile-time error
      }
      class InDirect
      {
          ~InDirect() {} // Compiles OK
      }
      
      And the CIL for ~Indirect() looks like this:
      
      .method family hidebysig virtual instance void
              Finalize() cil managed
      {
        // ...
      } // end of method Indirect::Finalize
      
    5. A struct is implicitly sealed, a class isn't.
      A struct can't be abstract, a class can.
      A struct can't call : base() in its constructor whereas a class with no explicit base class can.
      A struct can't extend another class, a class can.
      A struct can't declare protected members (for example, fields, nested types) a class can.
      A struct can't declare abstract function members, an abstract class can.
      A struct can't declare virtual function members, a class can.
      A struct can't declare sealed function members, a class can.
      A struct can't declare override function members, a class can.
      The one exception to this rule is that a struct can override the virtual methods of System.Object, viz, Equals(), and GetHashCode(), and ToString().

    0 讨论(0)
  • 2020-11-22 02:02

    Structs are the actual value - they can be empty but never null

    This is true, however also note that as of .NET 2 structs support a Nullable version and C# supplies some syntactic sugar to make it easier to use.

    int? value = null;
    value  = 1;
    
    0 讨论(0)
  • 2020-11-22 02:03

    Just to make it complete, there is another difference when using the Equals method, which is inherited by all classes and structures.

    Lets's say we have a class and a structure:

    class A{
      public int a, b;
    }
    struct B{
      public int a, b;
    }
    

    and in the Main method, we have 4 objects.

    static void Main{
      A c1 = new A(), c2 = new A();
      c1.a = c1.b = c2.a = c2.b = 1;
      B s1 = new B(), s2 = new B();
      s1.a = s1.b = s2.a = s2.b = 1;
    }
    

    Then:

    s1.Equals(s2) // true
    s1.Equals(c1) // false
    c1.Equals(c2) // false
    c1 == c2 // false
    

    So, structures are suited for numeric-like objects, like points (save x and y coordinates). And classes are suited for others. Even if 2 people have same name, height, weight..., they are still 2 people.

    0 讨论(0)
提交回复
热议问题