The type 'T1' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable<T>' - c#

Here iam getting error
The type 'string' must be a non-nullable value type in order to use it as parameter 'T1' in the generic type or method 'GetDataKeyValue(System.Web.UI.WebControls.GridView, int, string)'
String Process = GetDataKeyValue<String>(gvTargetRate, RowIndex, "Process");
Here iam getting error
The type 'T1' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable'
private Nullable<T> GetDataKeyValue<T>(GridView gv, int RowIndex, T column)
{
if (column == null)
return default(T);
return (T)gv.DataKeys[RowIndex].Values[column];
}

You can't create a Nullable<> out of any type. As the compiler tells you, you can only do that for value types. Since the method isn't restricted to any type, it can't say for sure you won't pass it, let's say, an object.
What you want isn't possible, actually, as explained in this question and its answer.
And by the way, T isn't a nullable type by definition, so default(T) will become a non-null value in the case of value types. string is on object, so it can be null without the use of Nullable<T>.

The Nullable type requires that T is a non-nullable value type, for example int or DateTime. Reference types like string can already be null. There would be no point in allowing things like Nullable so it is disallowed.
more info.

Related

Nullable generic parameter C# [duplicate]

Let's say we have some generic method with 2 parameters:
private void TestConstraints<TKey>(TKey key, TKey? nullableKey)
where TKey : notnull { }
That's perfectly fine from .NET6 perspective, where not nullable reference types were added. But using attempt is failing with reason CS8714 type can't be used as parameter:
private void TestMethod()
{
var id = 5;
int? nullableId = null;
TestConstraints(id, nullableId);
}
Warning CS8714 The type 'int?' cannot be used as type parameter 'TKey' in the generic type or method 'TestClass.TestConstraints(TKey, TKey?)'. Nullability of type argument 'int?' doesn't match 'notnull' constraint.
Specifying type explicitly as int does not help.
Could someone clarify if I could operate this way (defining input parameters as TKey?) or not, and where in documentation it is stated?
Compiler version:
Microsoft (R) Build Engine version 17.2.0+41abc5629
For unconstrained (neither to struct nor to class) generic type parameter T - T? is handled differently for value types and reference types. From the docs:
If the type argument for T is a reference type, T? references the corresponding nullable reference type. For example, if T is a string, then T? is a string?.
If the type argument for T is a value type, T? references the same value type, T. For example, if T is an int, the T? is also an int.
If the type argument for T is a nullable reference type, T? references that same nullable reference type. For example, if T is a string?, then T? is also a string?.
If the type argument for T is a nullable value type, T? references that same nullable value type. For example, if T is a int?, then T? is also a int?.
This happens partially due to the differences in how nullable reference and nullable value types are handled, cause nullable value types are actually separate types - Nullable<T>.
For TestConstraints let's imagine that T is int then according to the rules the signature becomes TestConstraints<int>(int key, int nullableKey) which obviously will not compile for the TestConstraints<int>(id, nullableId) call due to the type mismatch (TestConstraints<int>(id, nullableId.Value) will compile but throw at the runtime).
For int? (Nullable<int>) the signature becomes TestConstraints<int?>(int? key, int? nullableKey) which will compile (due to the implicit conversion T -> Nullable<T>) but obviously will fail the generic constraint with the warning.
The workaround can be to introduce two overloads, one for struct, one for class and let the compiler figure it out:
private void TestConstraints<TKey>(TKey key, TKey? nullableKey)
where TKey : struct
{ }
private void TestConstraints<TKey>(TKey key, TKey? nullableKey)
where TKey : class
{ }

How can I initialize a System.Nullable<Int32>? [duplicate]

This question already has answers here:
GetType on Nullable Boolean
(2 answers)
Closed 1 year ago.
I need a Nullable type but how do I initialize such a variable? Whenever I try to do this it automatically converts to a normal Int32.
Nullable<Int32> nullableInt32 = new Nullable<Int32>(3);
Console.WriteLine(nullableInt32.GetType()); // gives me System.Int32
Is this a bug? How can I actually initalize the Nullable?
From Microsoft's documentation:
If you want to determine whether an instance is of a nullable value type, don't use the Object.GetType method to get a Type instance to be tested with the preceding code. When you call the Object.GetType method on an instance of a nullable value type, the instance is boxed to Object. As boxing of a non-null instance of a nullable value type is equivalent to boxing of a value of the underlying type, GetType returns a Type instance that represents the underlying type of a nullable value type.
So your int? gets boxed to int, and GetType() is called on the boxed instance.
Unless you know the type at compile time and use typeof, there is no way to get a type of a nullable object:
var type = typeof(int?);
In practice this shouldn't matter because if you don't know the type at compile time, it means you're using some sort of type erasure (i.e. a cast to object), and that means boxing, and nullable value types don't exist there. You can't use polymorphism because that doesn't work with value types.
If you think you have a valid need for this, feel free to explain your use case in the comments.

The type must be a non-nullable value

I'm trying to create a NativeArray of type Dictionary and i get this error:
The type Realtime.Messaging.Internal.ConcurrentDictionary<string,Chunk>' must be a non-nullable value type in order to use it as type parameterT' in the generic type or method `Unity.Collections.NativeArray'
NativeArray<ConcurrentDictionary<string, Chunk>> dictionary = new NativeArray<ConcurrentDictionary<string, Chunk>>(8, Allocator.TempJob);
I'm new to Unity and C#, this question was probably asked before but i've been searching for a fix and couldn't find anything.
How can I fix this?
The answer is in the error message you get: .. must be a non-nullable value type... ConcurrentDictionary is a reference type and it seems that NativeArray has a type parameter constraint to accept only structs, the kind of constraint as the following:
class Foo<T> where T:struct{}
This means that you can only create NativeArray of value types (structs): int, byte, char, ...etc, or your own structs...

Why isn't null an instance of a Nullable<> type?

While writing tests that involved manual type checking I came across the fact that null does not evaluate as an instance of Nullable<> types, e.g. for the type Nullable<int> (which is the same as int?) the following statement is false
null is int?
while assigning null to int? is valid. Why is this so?
Well, why should nullables be special? This doesn't stand for any reference type, period:
var isObject = null is object;
Will give you a compile time error:
Error CS0184: The given expression is never of the provided ('object') type
Nullable<T> is a red herring here.
The type of null is the null type and its assignable to any reference type or nullable type because there is an implicit conversion (§2.4.4.6).
This is operator according to the spec works the following way (§7.10.10):
The is operator is used to dynamically check if the run-time type of an object is compatible with a given type. The result of the operation E is T, where E is an expression and T is a type, is a boolean value indicating whether E can successfully be converted to type T by a reference conversion, a boxing conversion, or an unboxing conversion. The operation is evaluated as follows, after type arguments have been substituted for all type parameters:
If E is an anonymous function, a compile-time error occurs
If E is a method group or the null literal, or if the type of E is a reference type or a nullable type and the value of E is null, the result is false. (...)
Bolded part for clarification.
Read this and this answer for more info.
What may be confusing is that null can be a value and a type.
If you compare or assign null the following implicit conversion is used to first convert the value to a Nullable.
public static implicit operator Nullable<T> (
T value
)
If you are using is not a value but a type comparison will be done. As null is of type null and not Nullable<T> they aren't equal.
In sort:-by making any value type nullable,null wont get converted to that type or null is not of that type.In case of nullable if the variable is assigned to null, HasValue property of sturct becomes false and then boxing will return reference for null but it doesn't mean it is of that particular value type.
you need to look into implementation and working of
Nullable<T>
Fundamental Properties
The two fundamental members of the Nullable structure are the HasValue and Value properties. If the HasValue property for a Nullable object is true, the value of the object can be accessed with the Value property. If the HasValue property is false, the value of the object is undefined and an attempt to access the Value property throws an InvalidOperationException.
Boxing and Unboxing
When a nullable type is boxed, the common language runtime automatically boxes the underlying value of the Nullable object, not the Nullable object itself. That is, if the HasValue property is true, the contents of the Value property is boxed. When the underlying value of a nullable type is unboxed, the common language runtime creates a new Nullable structure initialized to the underlying value.
If the HasValue property of a nullable type is false, the result of a boxing operation is null. Consequently, if a boxed nullable type is passed to a method that expects an object argument, that method must be prepared to handle the case where the argument is null. When null is unboxed into a nullable type, the common language runtime creates a new Nullable structure and initializes its HasValue property to false.
i have just copied this line from Microsoft docs it will give you some idea about hole concept
for reading entire documentation link is bellow
https://learn.microsoft.com/en-us/dotnet/api/system.nullable-1?view=netframework-4.7

Why string or object type don't support nullable reference type? [duplicate]

This question already has answers here:
C# nullable string error
(5 answers)
Closed 8 years ago.
Look into following code block:
//Declaring nullable variables.
//Valid for int, char, long...
Nullable<int> _intVar;
Nullable<char> _charVar;
//trying to declare nullable string/object variables
//gives compile time error.
Nullable<string> _stringVar;
Nullable<object> _objVar;
While compiling code compiler gives following error message:
The type 'string'/'object' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable'
I read it several times but still unable to understand. Can anyone clarify this? Why object or string dont support nullable reference type?
object and string are reference types, so they're already nullable. For example, this is already valid:
string x = null;
The Nullable<T> generic type is only for cases where T is a non-nullable value type.
In the declaration for Nullable<T> there is a constraint on T:
public struct Nullable<T> where T : struct
That where T : struct is precisely the part that constrains T to be a non-nullable value type.
Nullable<T> is defined as:
public struct Nullable<T> where T : struct
meaning: it only works on value-type T (excluding Nullable<TSomethingElse> itself).
You cannot use Nullable<T> on reference-types (or on Nullable<T>), but you don't need to since all reference-types (including object and string) are already "nullable", in that you can assign null to them.
string and object are reference types, and therefore are "nullable" already. The Nullable<T> type exists as a wrapper around value types that don't support null out of the box.
string myString = null //fine
int myInt = null //compiler error

Categories