How to create non-nullable value types like int, bool, etc. in C#?
Yes, these are called struct.
Structs are value types, just like int, bool and others.
They have some rules/recommendations related to them: (I think these are the most important)
a struct is passed and assigned by value, when not using ref or out keywords... this means that everything you put inside a struct will be copied when assigning or passing it to a method. That is why you should not make large structs.
you cannot define a parameterless constructor for a struct in C#
structs are better to be immutable, and have no property setters. You can get into real trouble by making mutable structs.
Other rules can be found within Microsoft docs about structs.
As for non-nullable reference types... this is not possible. You must check for nulls inside your code, manually.
7 years later and this is now possible
Install .NET Core 3.0 which includes C# 8.
Set the language version to 8.0: <LangVersion>8.0</LangVersion> to your .csproj file.
Add the property <NullableReferenceTypes>true</NullableReferenceTypes> (to your .csproj)
More details on his this affects writing code and your existing code here:
https://praeclarum.org/2018/12/17/nullable-reference-types.html
You can define a struct:
A struct type is a value type that is typically used to encapsulate small groups of related variables, such as the coordinates of a rectangle or the characteristics of an item in an inventory. The following example shows a simple struct declaration:
public struct Book
{
public decimal price;
public string title;
public string author;
}
However, you can't define aliases like int for System.Int32 and need to refer with the full name MyNamespace.Book (or Book with using MyNamespace;) to your struct.
Related
Intro
So far I am trying to wrap my head around structs. I have found many answers on the Topic "When to use a struct". Most of them are vague such as advice against the use of structs in general, with few exceptions. There are explanations of when to use structs (few examples):
immutable Data
value semantics as opposed to reference semantics
need them in code passing structured data to/from C/C++
Do not use structs unless you need them
But no example code as to when this case actually happens that it makes sense.
probably one of the most well known Questions/Answers is this one:
When should I use a struct rather than a class in C#?
Project structure
class StorageBlock<Type>:
/// this is a storage block. It is not a struct because the data is not immutable and it
/// should be passed by reference
public class StorageBlock<Type>
{
Type[] Data;
/* other stuff */
}
methodBlockSearcher():
public (StorageBlock<Type> FoundBlock, int FoundIndex) SearchBlock(Type searchForThisElement)
{
StorageBlock<Type> found = Blocks.Find(searchForThisElement);
int index = Array.IndexOf(found.Data, searchForThisElement);
return (found,index);
}
caller example:
(StorageBlock<Type> FoundBlock, int FoundIndex) searchResult = SearchBlock(searchElement);
/* process SearchResult(s) */
Questions
I wonder if it makes sense to convert (StorageBlock<Type> FoundBlock, int FoundIndex) searchResult to a struct. The search result should be immutable. It is only there to provide a return from specific indexing operations.
something like this:
struct BlockIndex
{
StorageBlock<Type> Block;
int Index;
}
Because a struct is a DataType, not a reference type, I also wonder if BlockIndex.Block (which is a class) will be a reference to the instance of block or a copy of the found block.
It seems like you're comparing structs to tuples (which are compiled to ValueTuple, not Tuple), not structs to classes (which is the more common question and the context of the original suggestions). Defining tuples with that syntax is a more recent construct in C# so I don't know that there is a best practice yet on whether to explicitly define a struct or use a tuple.
Behind-the-scenes, tuples are implemented as ValueTuple structs, so there should be minimal (if any) performance difference by defining a struct. It's more for coding convenience than performance.
As a pragmatist, I would say to continue using tuples until you have a measurable problem.
The search result should be immutable
This is the only thing I see that would make me consider defining a readonly struct, since ValueTuple is not immutable by default.
Because a struct is a [value type], not a reference type, I also wonder if BlockIndex.Block (which is a class) will be a reference to the instance of block or a copy of the found block.
It will still be a reference. Reference types do not cease to be reference types just because they're a property of a struct. The value of the reference will be carried along with the struct just like an integer would.
System.Uri seems to be a perfect candidate for being a struct but the good folks at Microsoft decided to make it a class. It is clearly a value object -> there is no sense in having two different instances of "https://stackoverflow.com" and so it has struct-y equality rules. I can't see any setters on the public API either, so it is immutable.
Is there some implementation detail which dictates it must be a class?
A struct would always have a default constructor (where all fields would be initialized to their default values). This could cause issues, for example, with some of the internal fields.
One example is that the existing constructor ensures that m_String can't be null - https://referencesource.microsoft.com/#system/net/system/UriExt.cs,39 . If you made this a struct, you can't easily achieve that in C#. So, everywhere you read from m_String you'd need to add a null check (which is not required if it is a class).
Additionally, as others have pointed out, the docs have other guidance on choosing when to use struct:
✓ CONSIDER defining a struct instead of a class if instances of the
type are small and commonly short-lived or are commonly embedded in
other objects.
X AVOID defining a struct unless the type has all of the following
characteristics:
It logically represents a single value, similar to primitive types
(int, double, etc.).
It has an instance size under 16 bytes.
It is immutable.
It will not have to be boxed frequently.
The 16 byte requirement, in particular, is likely to be problematic for Uri.
An int is 32 bits. All those bits are used to store an int value. Why can an int also contain functions like ToString() and GetType()?
Whilst you're treating an int as an int, the system knows exactly what type it's dealing with and can go directly to the methods. As soon as you need to use an int in a more ambiguous situation (where the type of the object is unknown), you have to box the int into an object.
At that point, the box contains not just the actual data for the int but also the usual things associated with reference types - such as the reference to the Type to allow methods to be found.
This same theory applies to all value types - whilst it's stored in a variable of the correct type, the exact type is known. This is why value types cannot inherit or be inherited from - so that the type of the variable (field, etc) informs the system of the exact type to use, and from the type, the methods.
The functions themselves are pointed to by a method table. When calling a virtual function on a struct, the struct is first boxed to create an object on the heap with an object header. One of the fields of the header points into the method table and the method to call can be looked up from there.
If the struct type overrides the virtual methods in question then the boxing can be avoided since the location of the method can be determined statically.
In C# int and every other object derives from object type, which contains those methods. It doesn't matter how much memory it needs to allocate. These are the most basics of c# and I suggest you reading any C# book or at least turorial befor asking questions here.
Apparently you can change the this value from anywhere in your struct (but not in classes):
struct Point
{
public Point(int x, int y)
{
this = new Point();
X = x; Y = y;
}
int X; int Y;
}
I've neither seen this before nor ever needed it. Why would one ever want to do that? Eric Lippert reminds us that a feature must be justified to be implemented. What great use case could justify this? Are there any scenarios where this is invaluable? I couldn't find any documentation on it1.
Also, for calling constructors there is already a better known alternative syntax, so this feature is sometimes redundant:
public Point(int x, int y)
: this()
{
X = x; Y = y;
}
I found this feature in an example in Jeffrey Richter's CLR via C# 4th edition.
1) Apparently it is in the C# specification.
Good question!
Value types are, by definition, copied by value. If this was not actually an alias to a storage location then the constructor would be initializing a copy rather than initializing the variable you intend to initialize. Which would make the constructor rather less useful! And similarly for methods; yes, mutable structs are evil but if you are going to make a mutable struct then again, this has to be the variable that is being mutated, not a copy of its value.
The behaviour you are describing is a logical consequence of that design decision: since this aliases a variable, you can assign to it, same as you can assign to any other variable.
It is somewhat odd to assign directly to this like that, rather than assigning to its fields. It is even more odd to assign directly to this and then overwrite 100% of that assignment!
An alternative design which would avoid making this an alias to the receiver's storage would be to allocate this off the short-term storage pool, initialize it in the ctor, and then return it by value. The down side of that approach is that it makes copy elision optimizations pretty much impossible, and it makes ctors and methods weirdly inconsistent.
Also, I couldn't find any documentation on it.
Did you try looking in the C# spec? Because I can find documentation on it (7.6.7):
When this is used in a primary-expression within an instance constructor of a struct, it is classified as a variable. The type of the variable is the instance type (§10.3.1) of the struct within which the usage occurs, and the variable represents the struct being constructed. The this variable of an instance constructor of a struct behaves exactly the same as an out parameter of the struct type—in particular, this means that the variable must be definitely assigned in every execution path of the instance constructor.
When this is used in a primary-expression within an instance method or instance accessor of a struct, it is classified as a variable. The type of the variable is the instance type (§10.3.1) of the struct within which the usage occurs.
If the method or accessor is not an iterator (§10.14), the this variable represents the struct for which the method or accessor was invoked, and behaves exactly the same as a ref parameter of the struct type.
If the method or accessor is an iterator, the this variable represents a copy of the struct for which the method or accessor was invoked, and behaves exactly the same as a value parameter of the struct type.
As to a use case for it, I can't immediately think of many - about the only thing I've got is if the values you want to assign in the constructor are expensive to compute, and you've got a cached value you want to copy into this, it might be convenient.
A storage location of value type in an aggregation of storage locations comprising that type's public and private fields. Passing a value type an an ordinary (value) parameter will physically and semantically pass the contents of all its fields. Passing a value type as a ref parameter is semantically pass the contents of all its fields, though a single "byref" is used to pass all of them.
Calling a method on a struct is equivalent to passing the struct (and thus all its fields) as a ref parameter, except for one wrinkle: normally, neither C# nor vb.net will allow a read-only value to be passed as a ref parameter. Both, however, will allow struct methods to be invoked on read-only values or temporary values. They do this by making a copy of all the struct (and thus all of its fields), and then passing that copy as a ref parameter.
Because of this behavior, some people call mutable structs "evil", but the only thing that's evil is the fact that neither C# or vb.net defines any attribute to indicate whether a struct member or property should be invokable on things that can't be directly passed by ref.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
A lot of times the answer is merely when I want things to be allocated on a stack instead of the heap.. assuming I dont know what the stack and the heap are (and please dont try to explain it here), when exactly should I be using structs instead of classes?
Here is the answer I've been giving out, but please tell me if I'm wrong or falling short of a better answer:
I create structs usually when I have enums that I want to add more data to. For instance, I might start with a simple enum:
public enum Colors { Blue, Green, Red }
Then if I need to store more aspects of this data I go to structs:
public struct Color
{
string Name;
int HexValue;
string Description;
}
public class Colors
{
public static Color Blue;
public static Color Red;
public static Color Green;
static Colors()
{
Blue = new Color("Blue", 1234, "A light blue"
}
}
The point is... similar to enums, I use structs just when I want to declare a bunch of types.
struct vs class in .NET
The real time to use a struct is when you want value type like properties. Value types behave very differently from reference types, and the difference can be shocking and bug inducing if you aren't aware. For example a struct is copied into (and out of) method calls.
The heap vs stack isn't a compelling argument to me. In a typical .NET app, how often do you care about where the object lives?
I very rarely use structs in .NET apps. The only place I've truly used them was in a game where I wanted value type like properties for objects like vectors and such.
struct vs class in C++
This is a much simpler question to answer. structs and classes in C++ are identical to each other with only one minor difference. Everything in a C++ struct is public by default, where as everything in a C++ class is private by default. That is the only difference.
Simplistically, structs are for data, classes are for data and the manipulations of those data.
well in C++ land, you can allocate a struct (or class) on the stack or the heap... I generally use a struct when the default public access to everything is useful and class when I want to encapsulate... I also use structs for functors that need state.
You have this labelled with C#, C++ and "language-agnostic". The fact is though, the difference between structs and classes in C# and C++ are completely different, so this is not a language-agnostic question.
In C++ class is syntactic sugar for struct with different default visibility. The reason is that C had a struct and only had "public" visibility (indeed, it's not even a fully meaningful statement in C, there's no such thing as OO-style information hiding in C).
C++ wanted to be compatible with C so it had to keep struct default to everything visible. C++ also wanted to follow good OO rules, in which things are private by default, so it introduced class to do exactly the same, but with different default visibility.
Generally you use struct when you are closer to C-style use; no or relatively simple member functions (methods), simple construction, ability to change all fields from the outside ("Plain Old Data"). class is generally used for anything else, and hence more common.
In C# a struct has value semantics while a class has reference semantics (in C++ both classes and structs have value semantics, but you can also use types that access them with reference semantics). A struct, as a value-type is self-contained (the variable contains the actual value(s) directly) while a class, as a reference type refers to another value.
Some other differences are entailed by this. The fact that we can alias reference types directly (which has both good and bad effects) comes from this. So too do differences in what equality means:
A value type has a concept of equality based on the value contained, which can optionally be redefined (there are logical restrictions on how this redefinition can happen*). A reference type has a concept of identity that is meaningless with value types (as they cannot be directly aliased, so two such values cannot be identical) that can not be redefined, which is also gives the default for its concept of equality. By default, == deals with this value-based equality when it comes to value types†, but with identity when it comes to reference types. Also, even when a reference type is given a value-based concept of equality, and has it used for == it never loses the ability to be compared to another reference for identity.
Another difference entailed by this is that reference types can be null - a value that refers to another value allows for a value that doesn't refer to any value, which is what a null reference is.
Also, some of the advantages of keeping value-types small relate to this, since being based on value, they are copied by value when passed to functions.
Some other differences are implied but not entailed by this. That it's often a good idea to make value types immutable is implied but not entailed by the core difference because while there are advantages to be found without considering implementation matters, there are also advantages in doing so with reference types (indeed some relating to safety with aliases apply more immediately to reference types) and reasons why one may break this guideline - so it's not a hard and fast rule (with nested value types the risks involved are so heavily reduced that I would have few qualms in making a nested value type mutable, even though my style leans heavily to making even reference types immutable when at all practical).
Some further differences between value types and reference types are arguably implementation details. That a value type in a local variable has the value stored on the stack has been argued as an implementation detail; probably a pretty obvious one if your implementation has a stack, and certainly an important one in some cases, but not core to the definition. It's also often overstated (for a start, a reference type in a local variable also has the reference itself in the stack, for another there are plenty of times when a value type value is stored in the heap).
Some further advantages in value types being small relate to this.
Therefore in C# a struct when you are solely concerned with value-semantics and will not want to alias (string is an example of a case where value-semantics are very important, but you would want to alias, so it is a class to make it a reference-type). It's also a very good idea for such types to be immutable and an extremely good idea for such types to have fields that total to less than 16bytes - for a larger struct or a struct that needs to be mutable it may well be wise to use a class instead, even if the value-semantics make struct your first choice.
In C++, technically it doesn't matter. You could use struct for polymorphic object and class for PODs. The language wouldn't care, though your coworkers may plot a bloody revenge. Aside from default access, there's no difference between class and struct.
Ultimately, the most important consideration is that you pick a coding style, and apply it consitantly. Maybe that means everything is classes, or maybe PODs are structs. You need to decide for yourself, taking in to consideration any coding practices applied by whomever you work for.
As for myself, I only use structs if the object has only public members and no virtuals. They might have data only or data and methods. Typically I use structs for buckets of data that may or may not have simple operations associated with them, usually to convert from one type to another. Hence they may also have constructors.
When to use struct...
When you want object to behave as a value type
When the required size of object is <=16 bytes roughly.
A struct is actually exactly the same thing as a class - with one difference: in a class, everything is private by default while in a struct, everything is public by default!
struct Color
{
string Name;
private:
int HexValue;
};
would be the same as
class Color
{
int HexValue;
public:
string Name;
};
I would say , use stack when your data is smaller in size and you don't want a few thoushands of this object because it can hurt ou back a lot because as already mentioned that value types are copied by nature so pasing few thoushands of objects which is copied by value is not a good idea also.
Second point , i would like to include is when you only want data for most of the time and data is numeric most of the time , you can use stack.