gpt4 book ai didi

c# - 我应该如何处理关于 C# 8.0 中的 nullable 选项的泛型问题?

转载 作者:行者123 更新时间:2023-12-03 20:23:27 25 4
gpt4 key购买 nike

最近我在声明 T 时,在泛型类型是类还是结构之间遇到了麻烦。没有 class 的约束也不是 struct还有 #nullable选项被启用,那么泛型类型会出现一些意外的行为。例如,如果我构造一个类型为 T? 的成员和 T被指定为不可为空的结构类型,T? type 不作为可空结构运行。这是一个关于它的解释代码:

public class MyClass<T> {
...
public MyClass (T value, T? another) { ... }

public void DoExample () {
MyClass<int> a = new MyClass<int>(1, null); /* causes the CS1503 error, indicating int cannot receive null.
In other words, T? is still int, not the nullable int.*/
}
}
我应该怎么做才能解决这个问题?

也许已解决
最后,我找到了一个不完整但合理的解决方案来解决它。以下内容将帮助我们解决问题。
public class NullableWrapper<T> where T : notnull /* this constraint is not necessary
but if you want every type that specifies T to be non-nullable
and/or would not like to consider the null reference exception which may arise at Equals,
GetHashCode, and ToString, that would modify the type accuracy and/or your need. */ {
public T Value { get; set; } = default!;

internal NullableWrapper (T value) => this.Value = value;

public override bool Equals (object? obj) => this.Value.Equals(obj);
public override int GetHashCode () => this.Value.GetHashCode();
public override string? ToString () => $"NullableWrapper({this.Value})";

public static implicit operator NullableWrapper<T> (T itself)
=> new NullableWrapper<T>(itself);
public static implicit operator T (NullableWrapper<T> itself)
=> itself.Value;
}
然后,我之前的代码更改为如下所示:
public class MyClass<T> where T : notnull {
...
public MyClass (T value, NullableWrapper<T>? another) { ... }

public void DoExample () {
MyClass<int> a = new MyClass<int>(1, null); // this causes none of error.
MyClass<string> b = new MyClass<string>("hello", null); // similarly, no error happens.
MyClass<double> c = new MyClass<double>(2.6, 5.2); // it's equivalent to the previous.
MyClass<string> d = new MyClass<string>("asd", "def"); // as well.
}
}

最佳答案

  • 可空引用类型仅在编译时存在:Foo<string>Foo<string?>编译为相同的 Foo<System.String> .
  • 可空值类型不同:intSystem.Int32 , int?System.Nullable<System.Int32> .

  • 当您有 class MyClass<T> 没有 where T : struct ,编译器默认为可空引用类型行为,其中 int?没有意义,但仍被视为 Int32 ,而不是 Nullable<Int32>如您所料,和 null不是 Int32 的有效值.
    从 .NET 5/C# 9 开始,不可能有这样的泛型类型。它适用于 class或为 struct ,但不能两者兼而有之。
    @insane_developer 提供了一个 LDM session 的链接,讨论了这个问题:
    https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-11-25.md#problem-1-t-and-t-mean-different-things

    Problem 1: T? and T? mean different things

    The first problem is not technical, but one of perception and language regularity. Consider:

    public T? M1<T>(T t) where T : struct;
    public T? M2<T>(T t);

    var i1 = M1(7); // i1 is int?
    var i2 = M2(7); // i2 is int

    The declaration of M1 is legal today. Because T is constrained to a (nonnullable) value type, T? is known to be a nullable value type, and hence, when instantiated with int, the return type is int?.

    The declaration of M2 is what's proposed to allow. Because T is unconstrained, T? is "the type of default(T)". When instantiated with int the type of default(int) is int, so that is the return type.

    In other words, for the same provided T these two methods have different return types, even though the only difference is that one has a constraint on T but the other does not.

    The cognitive dissonance here was a major part of why we didn't embrace T? for unconstrained T.

    关于c# - 我应该如何处理关于 C# 8.0 中的 nullable 选项的泛型问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66029420/

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