C# struct, how to assign a null value? - c#

I have a list:
List<int, SomeStruct>
For some reason, it is not allowing me to assign null values to it. What do I do if I want to have no struct associated?

Use nullable types:
List<int, SomeStruct?>
You can't assign null to an element of the list because structs are value types, while null means an empty pointer, and so can only be assigned to reference type variables.
Also note that List as you're using it doesn't exist in .NET! Perhaps you want Dictionary?

In C# a struct is a 'value type', which can't be null.
If you really, really need to be able to null this, then make it into a 'nullable' type by adding a trailing question mark.
You should probably look into the details of this more first, though - it's quite likely you don't really want a 'struct' at all, but would be better with a 'class'.

Unless you have defined a custom generic collection, List<T, U> doesn't exist in the System.Collections.Generic namespace. Did you rather mean Dictionary<TKey, TValue>?
You can use Nullable types: Using Nullable Types (C# Programming Guide).
As for any ValueType, you need to specify explicitly that you will allow null values for your type. You can do so by concatenating the '?' character with your type name, or by marking it as Nullable, where T is the name of your structure.

All of the existing answers here are correct: in C# struct is a value type and cannot be null.
However some struct implementations (but definitely not all) follow a convention where the default/empty value is stored in a Empty static field. Sometimes there is also an IsEmpty property:
// System.Guid
public struct Guid : IFormattable, IComparable, IComparable<Guid>, IEquatable<Guid>
{
public static readonly Guid Empty;
...
}
// System.Drawing.Point
public struct Point
{
public static readonly Point Empty;
public bool IsEmpty { get; }
...
}
If the struct has an Empty field or IsEmpty property, then you can use it to test if the struct variable is Empty instead of null. Otherwise use a nullable wrapper as the other answers state.
If you are the programmer of the struct, strongly consider adding an Empty field and IsEmpty property if appropriate.

Related

Is it useful in a nullable enabled c# environment still to use NotNull attribute? Or does it makes no difference then?

Is it useful in a nullable enabled c# environment still to use NotNull attribute? Or does it make no difference then?
Let's say I have a parameter
case a
public static SomeExtensionMethod<T>([NotNull] this IList<T> source)
{
// stuff
}
case b
public static SomeExtensionMethod<T>([NotNull] this T source) where T: notnull
{
// stuff
}
NotNull will serve as a hint for the caller code. Not about what you can pass, but about whatever or not what you pass there will be null after the call.
If you mark a parameter as nullable and use the NotNull attribute, Roslyn will let you pass null, and assume that after that point the reference is not null. We can satisfy this contract by throwing if null is passed. This can be useful to make assertions.
public static void NotNullList<T>([NotNull] this IList<T>? source)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
// stuff
}
Perhaps you are thinking that we do not need such assertions. However, when a reference can be null, and we need to discard the null case. Well, of course, you may take advantage of NotNullIfNotNull instead.
Sadly, last time I checked, comparing a reference with null works as a hint to Roslyn that the reference can be null. So a simple if statement to discard null may not work as expected.
Another use of NotNull is for ref or out parameters. To guarantee to the caller that the reference will not be null.
In this example, passing null is allowed, and it is also guaranteed that the reference will not be null after the execution of the method. That is, we are saying that if you pass null, we will either throw or initialize it.
public static void DoSomethingWithRef<T>([NotNull] ref IList<T>? source)
{
if (source == null)
{
source = new List<T>();
}
// stuff
}
You can, of course use [return: NotNull] to communicate to the caller that return value is not null.
Now, how about generics?
If you do not constraint the generic, you can specify either a nullable or a not nullable reference type as the generic argument.
var x = new List<string?>();
var y = new List<string>();
In our generic code, without the constraint notnull, we do not know if the generic type is set to a nullable or not nullable type. Thus, the NotNull attribute remains useful to communicate to the caller when we can guarantee that something is not null.
Please keep in mind that class or struct constraint do not mix well with notnull. Code with those constraints will not be able to call cleanly into code with the notnull. In fact, notnull will tend to propagate. Futhermore, T with a notnull constraint does not allow to use T?.
Because of these reasons, I avoid the notnull constraint when possible. Sometimes even repeating myself:
public static IEnumerable<T> ExploreSequenceUntilNull<T>(T? initial, Func<T, T?> next)
where T : class
{
// ...
}
public static IEnumerable<T> ExploreSequenceUntilNull<T>(T? initial, Func<T, T?> next)
where T : struct
{
// ...
}
See there I'm saying that the input of next will not be null, but it is OK for it to return null. It is also OK for the initial parameter to be null. However, the returned IEnumerable will not have nulls. Yes, overload resolution can figure out which one to call. And yes, they are identical in source, except for the generic constraint. The actual code is different, as you know, for the struct T? means Nullable<T>.
What about the opposite (MaybeNull)? It remains useful with unconstrained generics, to communicate that a returned reference may be null (if the generic type allows for null). It is also similarly useful for parameters and fields in generic types.
Of course, we can just use ? when we are not dealing with a generic type.
You may also be interested in MaybeNullWhen.
sadly the documentation does not help much
AllowNull: // A non-nullable input argument may be null.
DisallowNull: // A nullable input argument should never be null.
MaybeNull: // A non-nullable return value may be null.
NotNull: // A nullable return value will never be null.
MaybeNullWhen: // A non-nullable input argument may be null when the method returns the specified bool value.
NotNullWhen: // A nullable input argument will not be null when the method returns the specified bool value.
NotNullIfNotNull: // A return value isn't null if the input argument for the specified parameter isn't null.

Alternative to IsNullOrEmpty for nullable types?

Is there a way to use IsNullOrEmpty with nullable types? The code above generates a build error when using IsNullOrEmpty with string? RunDate
public int MyMethod(string? RunDate = null)
{
string sql = string.Empty;
int rowsChanged = -1;
if (String.IsNullOrEmpty(RunDate))
{
//do stuff
}
}
It looks like you are intending to use ? like in TypeScript where it implies an optional value; but this is not the case in C#. In C#, The T? syntax is shorthand for Nullable<T>. The Nullable<T> struct has a constraint on T such T must also be a struct. System.String, is a class and not a struct, so it cannot be used with Nullable<T>.
The purpose of Nullable<T> is to contain a either a value of type T OR null, since struct based values cannot be null references themselves. All class based values can already contain null references, so it doesn't make sense to use them with Nullable<T>.
Try rewriting your code like this:
public int MyMethod(string RunDate = null)
{
string sql = string.Empty;
int rowsChanged = -1;
if (String.IsNullOrEmpty(RunDate))
{
//do stuff
}
}
It must be string? RunDate = null this line. You don't need to declare string as nullable type string? since string by itself is a reference type and thus defaults to null. It can simply be
public int MyMethod(string RunDate = null)
{
// rest of code
}
Quick answer, no.
Longer answer, not yet.
Right now, before C# 8 is released (well, as long as you're not using C# 8 preview that is), the ? symbol when used to specify nullable reference types, is a syntax error. Let's ignore C# 8 for the time being.
type? is translated to Nullable<type>, and the Nullable<T> struct is declared like this:
public struct Nullable<T> where T : struct
In other words, T cannot be string, so this, string?, is not legal. This is what is giving you the syntax error.
Until C# 8 is released, or you start using C# 8 Preview, there is nothing you can do, except remove the question mark.
What happens when C# 8 is released?
Well, type? for reference types will not translate to Nullable<T> but instead to T with knowledge about the nullability. For fields, properties, parameters, return types, basically anything that isn't a local variable, this will translate into a declaration with an attribute stating the nullability. For local variables the compiler will keep track of the nullability.
So in this case, string.IsNullOrEmpty will in fact work because the parameter will still fundamentally be a string, it will just be a string with the knowledge of nullability attached to it.
The ? operator is used to declare non-nullable types as nullable, and the compiler compiles them to be of type Nullable<T>.
The System.String is a reference type thus is nullable.
Remove the ? operator and things should work.

How can I check whether a struct has been instantiated? [duplicate]

This question already has answers here:
Null or default comparison of generic argument in C#
(14 answers)
Closed 2 years ago.
I have a struct that (for the purposes of this question) pretty much mimics the built in Point type.
I need to check that it has been instantiated before using it. When it was Point, I could do this:
if (this.p == null)
But that now generates the following error:
Operator '==' cannot be applied to operands of type 'ProportionPoint' and '<null>'
How can I compare my struct against null? Is there another way to check for instantiation?
A struct is a value type - it's never null.
You can check against default(ProportionPoint), which is the default value of the struct (e.g. zero). However, for a point, it may be that the default value - the origin - is also a "valid" value.
Instead you could use a Nullable<ProportionPoint>.
structs are value types and they can never be null contrary to reference types. You could check against the default value:
if (this.p.Equals(default(ProportionPoint)))
A struct can't be null. Its a value type, not a reference type. You need to check against the properties with the default values. Something like:
if(p.X == 0 && p.Y == 0)
because p is struct it never be null so you should compare it to it's default value. In order to check equivalence between your value and dafault value.
If you use == you will get
cannot be applied to operands of type 'ProportionPoint' and 'ProportionPoint' error
because structs do not get an implementation of == by default. so you need to overload the == and != operators in your struct like this:
public static bool operator ==(firstOperand op1, secondOperand2 op2)
{
return op1.Equals(op2);
}
public static bool operator !=(firstOperand op1, secondOperand2 op2)
{
return !op1.Equals(op2);
}
and then :
if (this.p == default(ProportionPoint))
another option is to use Equals directly:
f (this.p.Equals.default(ProportionPoint))
A struct can never be null, so you can't compare it to null. And a struct is always initialized - if not by you, then by the compiler with default values.
Use a nullable:
ProportionPoint? p1 = null;
if (p1 == null) ...
or
if (!p1.HasValue) ...
I made an extension method that only works with structs:
public static bool IsNull<T>(this T source) where T:struct
{
return source.Equals(default(T));
}
Calling convention:
if(myStruct.IsNull())
DoSomething();
I understand that it isn't really checking if it's null. However, if I gave it a more precise name, like IsEmpty or IsDefault, in six months I would forget it's there and upon seeing the list of methods available not pick it. It's not technically a null check; but conceptually it is.
Structs can't be null, but the workaround of checking a struct against its default can give a false negative if you actually want to store values equivalent to the defaults in it at any point.
(For example, a struct with the value (0,0,0) could be an untouched default, or it could be storing the origin point in 3D space.)
Another approach that avoids this false negative issue would be to just add another property to the struct - e.g. a bool or int - to track whether data has actually been stored in it. Then have any constructor that initializes the struct with actual data set this value to true/1. In the default struct, this value will still be false/0, so checking against default(MyStruct) should never give you a false negative even if all other data stored in it matches the default values.
public Struct MyStruct {
public float x { get; private set; }
public bool initialized { get; private set; }
public MyStruct(float _x){
x=_x;
initialized = true;
}
}
Unlike a variable or value of a reference type, which is a reference to either zero or one instances of that type, a struct variable or value is a struct instance. If one has a block of code which starts with {Point myPoint; ...}, and nothing in the block closes over MyPoint (closure occurs when there is a yield return within a block, or when a lambda or anonymous method uses a variable from an enclosing block), then an instance of Point will come into existence sometime before execution enters the block, and may cease to exist at any time after execution leaves the block. In any context where one can make use of a struct-type variable, the structure exists.
The reason one all structure types are regarded as having a do-nothing default constructor is that structure types come into existence implicitly. When one performs a statement like Point[] myPoints = new Point[100];, it creates a zero-filled array of 100 Point structures; in the process, 100 zero-filled Point instances instantly come into existence. In C++, if a type has a constructor, creating an array of that type will call the constructor on every element of the array in sequence before any code is given access to the array as a while. If an exception is thrown while constructing any element, compiler-generated code will run the deterministic destructor on every element which had been successfully created before the array itself evaporates. While this is a very powerful feature, including it within .net would have substantially complicated the Framework.
You can't check struct on null but you can check on default unitialized value like this:
if (instanceOfYourStruct == default)

Nullable List<> as out parameter

Is this possible?
private void Test(out List<ExampleClass>? ExClass)
{
}
A nullable List<> that is also an out parameter?
List<T> is a reference type (class), so no ? is required. Just assign null to ExClass parameter in method body.
As Anton said, you don't need to use Nullable<T> - but it could certainly be an out parameter:
private void Test(out List<ExampleClass> foo)
It's possible you're confusing a nullable List<T> with a List<T?> which would be valid for value types... for example, you could use:
private void Test(out List<Guid?> foo)
which would be an out parameter which is a list of nullable guids.
On the other hand, it's not generally nice to have out parameters in void methods - you should usually use it as the return type instead.
Use ? just for nullable ValueTypes.
Being an out parameter or not is irrelevant here. But you cannot make a Nullable<T> with a class; T must be a struct. Otherwise the compiler will complain.
In addition to this, it is considered bad style to capitalise the name of a parameter (use exClass instead of ExClass). Your programs will work the same, but anybody reading your code might be misled.

Do C# Nullable variables still function as value types?

If I declare a nullable (either via Nullable or the ? symbol) variable from a value type, does it still respect the rules of value types (i.e. pass by value by default, deallocated when it falls out of scope, not when the garbage collector runs) or does it turn into a reference type since it's actually of type Nullable?
The documentation is here:
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx
As you can see, the documentation describes this as the "nullable structure", indicating that it is a value type. Also, the documentation gives the first lines of the declaration of the type:
public struct Nullable<T> where T : struct, new()
again showing that the type is a value type.
Yes, System.Nullable is a generic Struct, ie value type.
Nullable value types are essentially just a struct wrapper around a value type which allows them to be flagged as null.
something like this:
struct Nullable<T>
{
public T Value;
public bool HasValue;
}
I believe it's actually more complex than that under the hood, and the compiler does lots of nice stuff for you so you can write for example if(myInt == null). But yes, they are still value types.

Categories