开发者

C# why need struct if class can cover it?

开发者 https://www.devze.com 2022-12-21 04:10 出处:网络
Just wondering why we need struct if class can do all struct can and more? put value types in class has no side effect, I think.

Just wondering why we need struct if class can do all struct can and more? put value types in class has no side effect, I think.

EDIT: cannot see any strong reasons to use struct

A struct is similar to a class, with the following key differences:

  • A struct is a value type, whereas a class is a reference type.
  • A struct does not开发者_开发问答 support inheritance (other than implicitly deriving from object).
  • A struct can have all the members a class can, except the following:
  • A parameterless constructor
  • A finalizer
  • Virtual members

A struct is used instead of a class when value type semantics are desirable. Good examples of structs are numeric types, where it is more natural for assignment to copy a value rather than a reference. Because a struct is a value type, each instance does not require instantiation of an object on the heap. This can be important when creating many instances of a type.


Custom value types aren't absolutely necessary - Java does without them, for example. However, they can still be useful.

For example, in Noda Time we're using them pretty extensively, as an efficient way of representing things like instants without the overhead of an object being involved.

I wouldn't say that "class can do all struct can and more" - they behave differently, and should be thought of differently.


Why use a struct when a class works? Because sometimes a class doesn't work.

In addition to the performance reasons mentioned by Reed Copsey (short version: fewer objects that the GC needs to track, allowing the GC to do a better job), there is one place where structures must be used: P/Invoke to functions that require by-value structures or structure members.

For example, suppose you wanted to invoke the CreateProcess() function. Further suppose that you wanted to use a STARTUPINFOEX structure for the lpStartupInfo parameter to CreateProcess().

Well, what's STARTUPINFOEX? This:

typedef struct _STARTUPINFOEX {
    STARTUPINFO                    StartupInfo;
    PPROC_THREAD_ATTRIBUTE_LIST    lpAttributeList;
} STARTUPINFOEX, *LPSTARTUPINFOEX;

Notice that STARTUPINFOEX contains STARTUPINFO as its first member. STARTUPINFO is a structure.

Since classes are reference types, if we declared the corresponding C# type thus:

[StructLayout(LayoutKind.Sequential)]
class STARTUPINFO { /* ... */ }

class STARTUPINFOEX { public STARTUPINFO StartupInfo; /* ... */ }

The corresponding in-memory layout would be wrong, as STARTUPINFOEX.StartupInfo would be a pointer (4 bytes on ILP32 platforms), NOT a structure (as is required, 68 bytes in size on ILP32 platforms).

So, to support invoking arbitrary functions which accept arbitrary structures (which is what P/Invoke is all about), one of two things are necessary:

  1. Fully support value types. This allows C# to declare a value type for STARTUPINFO which will have the correct in-memory layout for marshaling (i.e. struct support, as C# has).

  2. Some alternate syntax within P/Invokeable structures which would inform the runtime marshaler that this member should be laid out as a value type instead of as a pointer.

(2) is a workable solution (and may have been used in J/Direct in Visual J++; I don't remember), but given that proper value types are more flexible, enable a number of performance optimizations not otherwise achievable, and make sensible use within P/Invoke scenarios, it's no surprise that C# supports value types.


In general, use a class.

Only use a struct when you absolutely need value type semantics.


Structs are also often required for performance reasons. Arrays of structs take quite a bit less memory, and get much better cache coherency than an array of object references. This is very important if you're working with something like a rendering system, and need to generate 5 million vertices, for example.

For details, see Rico Mariani's Performance Quiz + Answers.


Structs are useful simply because they are passed by value, which can actually be useful in certain algorithms. This is actually something that classes CAN'T do.

struct ArrayPointer<T>
{
    public T[] Array;
    public int Offset;
}

You can pass this structure to a method and the method can alter the value of Offset for its own needs. Meanwhile, once you return from the method, it will behave as if Offset never changed.


  • Struct Vs Class in C#
  • C# Struct usage tips?
  • Why do we need struct? (C#)


For the average application developer, using classes is the norm. On the surface, classes make structs seem unnecessary, but when you dig deeper into the nitty-gritty details they are actually quite different.

See here for some differences between structs and classes.

The most well-known difference is that classes are reference-types and structs are value-types. This is important because it allows a library developer to control how instances of a data-type can be used.


1, performance. In some cases using structures we'll get much better performance.
2, data immutability. By changing some property of a struct you'll get a new struct. This is very useful in some cases
3, better control of in memory representation. We can exactly define how the struct is located in memory and this allows us to serialize and deserialize some binary data fast and efficiently.


It is almost a must to use for interop with underlying data structure used by win32 API. I suppose a very big reason to have it in .net could be due to that reason.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号