C#泛型可以支持Class还是null?

C#泛型可以支持Class还是null?,c#,generics,nullable,C#,Generics,Nullable,在我当前的项目中,我有一个值类 当前T可以是任何值,但我们必须支持Null值,因此当前我们以两种形式使用它: 值或值 我是否可以以任何方式创建一个值类,允许我指定Value或Value,但其效果是,对于类,值保持T,而对于结构,值保持T? 我们的目标是避免开发人员指定值之后出现问题,因为我们不能正确处理空值 Ie,我希望编译器支持避免错误 我是否可以以任何方式创建一个Value类,该类允许我指定Value或Value,但其效果是,对于类,值保持T,而对于结构,值保持T? 否,因为泛型类型约束中不

在我当前的项目中,我有一个

当前
T
可以是任何值,但我们必须支持
Null
值,因此当前我们以两种形式使用它:

我是否可以以任何方式创建一个值类,允许我指定
Value
Value
,但其效果是,对于类,值保持
T
,而对于结构,值保持
T?

我们的目标是避免开发人员指定
之后出现问题,因为我们不能正确处理空值

Ie,我希望编译器支持避免错误

我是否可以以任何方式创建一个
Value
类,该类允许我指定
Value
Value
,但其效果是,对于类,值保持
T
,而对于结构,值保持
T?

否,因为泛型类型约束中不能有“或”逻辑

要在泛型类型约束中实现“或”逻辑,必须创建两个单独的泛型类,每个类都有自己的泛型类型约束。请注意,这两个类可以继承自一个完全没有类型约束的共享泛型基类。
如果该基类型是抽象的,那么您可以确定使用者必须通过了派生类的类型约束检查(假设没有人添加其他派生类)

改变你的期望,而不是按照你现在想要的方式去做,会更合适

但我们必须支持
null

如果使用
default(T)
,而不是
null
,则问题得到解决

  • 对于类类型,
    default(MyClass)
    有效地解析为
    null
  • 对于结构,
    default(MyStruct)
    返回一个其属性都包含默认值的结构
default(MyStruct)
是使用“可空性”概念而不必使用文本
null
值的常用方法

用法示例:

public class Container<T>
{
    private readonly Random _random = new Random();
    public T DoSomething(T input)
    {
        //always returns "nothing"
        return default(T);
    }
}

public class MyClass
{
    public int Value { get; set; }
}

public struct MyStruct
{
    public int Value { get; set; }
}

public class Test
{
    public bool ContainerReturnsNothing<T>(T input)
    {
        var container = new Container<T>();

        var output = container.DoSomething(input);

        return output.Equals(default(T));
    }

    public void TestAClassAndAStruct()
    {
        ContainerReturnsNothing(new MyClass()  {Value = 1}); // true
        ContainerReturnsNothing(new MyStruct() {Value = 1}); // true
    }
}
  • default(MyStruct)
    将始终将
    IsConstructed
    设置为
    false
  • 每个实例化的结构将始终将
    IsConstructed
    设置为
    true
这就避免了这个问题,因为它们永远不会相等。换言之:

var myStruct = new MyStruct(0);

var isNull = myStruct.Equals(default(MyStruct));
isNull
为false,因为
myStruct
default(myStruct)
IsConstructed
包含不同的值(
true
false

如果使用原始示例中的
MyStruct
类运行相同的检查,
isNull
将为true,因为所有属性都匹配,即
MyStruct
default(MyStruct)
都将
值设置为
0

我是否可以以任何方式创建一个
Value
类,该类允许我指定
Value
Value
,但其效果是,对于类,值保持
T
,而对于结构,值保持
T?

否,因为泛型类型约束中不能有“或”逻辑

要在泛型类型约束中实现“或”逻辑,必须创建两个单独的泛型类,每个类都有自己的泛型类型约束。请注意,这两个类可以继承自一个完全没有类型约束的共享泛型基类。
如果该基类型是抽象的,那么您可以确定使用者必须通过了派生类的类型约束检查(假设没有人添加其他派生类)

改变你的期望,而不是按照你现在想要的方式去做,会更合适

但我们必须支持
null

如果使用
default(T)
,而不是
null
,则问题得到解决

  • 对于类类型,
    default(MyClass)
    有效地解析为
    null
  • 对于结构,
    default(MyStruct)
    返回一个其属性都包含默认值的结构
default(MyStruct)
是使用“可空性”概念而不必使用文本
null
值的常用方法

用法示例:

public class Container<T>
{
    private readonly Random _random = new Random();
    public T DoSomething(T input)
    {
        //always returns "nothing"
        return default(T);
    }
}

public class MyClass
{
    public int Value { get; set; }
}

public struct MyStruct
{
    public int Value { get; set; }
}

public class Test
{
    public bool ContainerReturnsNothing<T>(T input)
    {
        var container = new Container<T>();

        var output = container.DoSomething(input);

        return output.Equals(default(T));
    }

    public void TestAClassAndAStruct()
    {
        ContainerReturnsNothing(new MyClass()  {Value = 1}); // true
        ContainerReturnsNothing(new MyStruct() {Value = 1}); // true
    }
}
  • default(MyStruct)
    将始终将
    IsConstructed
    设置为
    false
  • 每个实例化的结构将始终将
    IsConstructed
    设置为
    true
这就避免了这个问题,因为它们永远不会相等。换言之:

var myStruct = new MyStruct(0);

var isNull = myStruct.Equals(default(MyStruct));
isNull
为false,因为
myStruct
default(myStruct)
IsConstructed
包含不同的值(
true
false


如果您使用原始示例中的
MyStruct
类运行相同的检查,
isNull
将为真,因为所有属性都匹配,即
MyStruct
default(MyStruct)
都将
属性值设置为
0

,我看不到任何可能性(最多为c#8)这应该如何工作
Nullable
(或
int?
)仍然只是一种值类型而不是引用,并且没有通用约束规定“
T
应该是
class
Nullable
”。因此,如果没有编译器支持,您可能会在value的构造函数中引发异常。您能描述一下什么是正确的null值处理吗?也许与
默认值(T)
相比更适合您?我们尝试介绍3个选项:1:我知道值,2:值为空,3:我不知道值。我们的值容器包含一个bool NoValue和一个对类型值的引用。因为某些参与方给我们null,所以我们必须使用nullable。