C# 泛型类中的可空类型

C# 泛型类中的可空类型,c#,generics,null,C#,Generics,Null,我需要创建一个类似于以下内容的类: class GenericClass<T> { public T[] Arr {get; } public GenericClass(int n) { Arr = new T[n]; for (int i = 0; i < n; i++) { Arr[i] = null; } } } class泛型类 { 公共T[]Arr

我需要创建一个类似于以下内容的类:

class GenericClass<T>
{
    public T[] Arr {get; }
    public GenericClass(int n)
    {
        Arr = new T[n];
        for (int i = 0; i < n; i++)
        {
            Arr[i] = null;
        }
    }
}
class泛型类
{
公共T[]Arr{get;}
公共泛型类(int n)
{
Arr=新的T[n];
对于(int i=0;i
但有一个编译器错误:

CS0403无法将null转换为类型参数“T”,因为它可能是不可为null的值类型。考虑使用“默认(t)”代替.< /P>
我不想使用
default(t)
,因为它可能与正常值相同,但我需要区分。我不知道类型,所以不能使用最小值。如何使用null?

如果类是值类型,则要使用可为null的类型实例化该类:

var obj = new GenericClass<int?>();
var obj=新的GenericClass();

然后,您可以使用
default(T)
而不是null而不会出现问题。您将得到一个
int?[]
数组,尽管您不需要显式地使用它,因为数组中的每个元素在实例化数组时都会自动获得默认值。

如果您知道
t
必须是可空类型,比如说,
null
,您可以强制用户在内部传递
Xyz
,并使
可为null
(又称
Xyz?
):

class GenericClass<T> where T : struct {
    public T?[] Arr {get; }
    public GenericClass(int n) {
        Arr = new T?[n]; // This will create an array of nulls, no need for a loop
    }
}
class GenericClass其中T:struct{
公共T?[]Arr{get;}
公共泛型类(int n){
Arr=newt?[n];//这将创建一个空数组,不需要循环
}
}

添加到声明中的
where T:struct
约束将阻止
GenericClass
实例化非值类型的参数。例如,尝试创建
GenericType
将导致编译时错误。

您实际上是在自食其果。NET中的数组会自动设置为该类型的默认值,因此只要类型的默认值为null(所有对象和可空值),那么只需创建数组就足以将所有项设置为null。如果没有多余的代码,您可能永远不会遇到任何问题,这取决于您试图如何使用此类

如果您试图允许像
GenericClass
这样的情况,并让它公开一个
int?
s数组,那么请执行此操作。
其中T:struct
强制提供的类型为值类型,从而允许您使用
T?
。在这种情况下,不能对泛型参数使用对象类型

class GenericClass<T> where T : struct
{
    public T?[] Arr { get; }
    public GenericClass(int n)
    {
        Arr = new T?[n];
    }
}

泛型的东西是,他们必须考虑代码< >代码>代码>字面上的任何可能性,包括一个不能是<代码> null >代码>的类型(包括基元和结构的值类型)。为了将泛型参数限制为可以是

null
的类型,需要添加
约束:

class GenericClass<T> where T : class
{
    public T[] Arr { get; private set; }
    public GenericClass(int n)
    {
        Arr = new T[n];
        for (int i = 0; i < n; i++)
        {
            Arr[i] = null;
        }
    }
}

它会很好的工作
default(T)
将为任何可为空的类型返回
null
,为任何不可为空的类型返回默认值。(0表示
int
,false表示
bool
,等等)

EDIT:作为另一种选择,您可以使用
Nullable
包装类型在内部表示对象。C#允许使用
运算符简写此语法:

class GenericClass<T>
{
    public T?[] Arr { get; private set; }
    public GenericClass(int n)
    {
        Arr = new T?[n];
    }
}
class泛型类
{
公共T?[]Arr{get;私有集;}
公共泛型类(int n)
{
Arr=新的T?[n];
}
}

顺便说一句,使用这种方法,不需要迭代数组的每个索引并将其设置为
null
,因为C#会为您处理它。

这是因为在编译时编译器不知道什么是不可能的(类或结构),您不能在泛型级别上使用null,这就是问题所在。如果您希望T是int(正则的,不可为null的),该怎么办?你不能分配一个int-null。不管怎样,偶尔我会发现我确实需要做一些事情,比如OP所说的——将
null
literal转换为
t
generic。在这些情况下,我使用了双重强制转换--
(T)(object)null
。不过,你几乎不必这样做。
Arr[i] = null;
Arr[i] = default(T);
class GenericClass<T>
{
    public T?[] Arr { get; private set; }
    public GenericClass(int n)
    {
        Arr = new T?[n];
    }
}