gpt4 book ai didi

c# - 你能定义一个接受*任何*可为空的类型、值或引用的泛型吗?

转载 作者:行者123 更新时间:2023-12-03 21:27:50 26 4
gpt4 key购买 nike

在 C# 中使用新的可为空引用类型。很高兴看到他们从 Swift 中挖走了这个!这是一个非常棒的功能!但是...因为它本质上是“固定在”语言上的,所以我正在努力创建一个泛型,它可以采用任何可空类型,无论是值还是引用,这在 Swift 中都是微不足道的。

考虑这个类:

public abstract class LabeledValue<TValue> {
public string? label { get; set; }
public TValue? value { get; set; }
}

这是我想要实现的目标,使用 Int以一个名为“Foo”的类为例:
public class LabeledInt : LabeledValue<Int>{}

var myLabeledIntA = new LabeledInt(){
label = "Forty Four",
value = 44
}

var myLabeledIntB = new LabeledInt(){
label = "Not Set",
value = null
}

public class LabeledFoo : LabeledValue<Foo>{}

var myLabeledFooA = new LabeledFoo(){
label = "Set",
value = new Foo()
}

var myLabeledFooB = new LabeledFoo(){
label = "Not Set",
value = null
}

这提示我必须将 TValue 定义为可空。但是,我找不到可以解决可为空值类型(即 Int?)和可为空引用类型(即 Foo?)的约束。如何编写这样的约束?

这些都行不通...
public abstract class LabeledValue<TValue>
where TValue : Nullable {
public string? label { get; set; }
public TValue? value { get; set; }
}

public abstract class LabeledValue<TValue>
where TValue : struct {
public string? label { get; set; }
public TValue? value { get; set; }
}

public abstract class LabeledValue<TValue> {
public string? label { get; set; }
public Nullable<TValue> value { get; set; }
}

请注意,我也尝试过这种想法,认为可空性可以作为实际类型参数传入,但随后它提示未设置“值”。
public abstract class LabeledValue<TValue> {
public string? label { get; set; }
public TValue value { get; set; }
}

public class LabeledInt : LabeledValue<Int?>{}

最佳答案

好的,找到了。您必须使用两个新的显式属性,AllowNullMaybeNull .

这是修改后的代码...

public abstract class LabeledValue<TValue> {

public string? label { get; set; }

[AllowNull, MaybeNull]
public TValue value { get; set; }
}

有了这个更改,我现在可以执行以下所有操作...
public class LabeledInt  : LabeledValue<int>{}
public class LabeledNInt : LabeledValue<int?>{}
public class LabeledFoo : LabeledValue<Foo>{}
public class LabeledNFoo : LabeledValue<Foo?>{}

并像这样使用它们......
var a = new LabeledInt();
a.Value = 4;
a.value = null // This won't compile

var b = new LabeledNInt();
b.Value = 4;
b.Value = null; // This compiles just fine

var c = new LabeledFoo();
c.Value = new Foo();
c.Value = null; // This won't compile

var d = new LabeledNFoo();
d.Value = new Foo();
d.Value = null; // This compiles just fine

Note: There is still a warning about Value being uninitialized, but it's only a warning, not an error. You have to make sure to explicitly set Value for non-null types before accessing it. Kind of defeats the purpose of using nullable/non-nullable types, but this is more a hack than a true solution which isn't actually possible since nullable value types are really the concrete Nullable<T> whereas nullable reference types are regular reference types just adorned with an attribute to let the compiler know not to accept nulls.

关于c# - 你能定义一个接受*任何*可为空的类型、值或引用的泛型吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59739194/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com