[英]How to check if generic function is called with nullable generic argument
I'm trying to write a generic function that behaves differently depending on whether it was called with an argument that allows nulls or not.我正在尝试编写一个泛型函数,该函数的行为取决于是否使用允许空值的参数调用它。 In pre-C#8 world I was using something like this:
在 C#8 之前的世界中,我使用的是这样的东西:
T MyFunc<T>()
{
object value = SomeExternalFunctionCall();
if (value == null)
{
if (typeof(T).AcceptsNulls())
{
return null;
}
else
{
throw new Exception($"{typeof(T).Name} does not support nulls");
}
}
return (T)value;
}
Where AcceptsNulls()
was like this:其中
AcceptsNulls()
是这样的:
public static bool IsAcceptNulls(this Type type)
{
if (type.IsValueType)
{
if (Nullable.GetUnderlyingType(type) != null)
{
return true;
}
return false;
}
return true;
}
So MyFunc
worked happily for both reference and value types, with proper support for nullable value types.因此,
MyFunc
对引用类型和值类型都能很好地工作,并适当支持可为空值类型。
But now I want to have it in a nullable-reference-types-enabled code.但现在我想将它放在一个启用可空引用类型的代码中。 And I'd like it to be able to distinguish
MyFunc<object>()
and MyFunc<object?>()
cases, so it would throw when handling a null value in former case, but not in latter.而且我希望它能够区分
MyFunc<object>()
和MyFunc<object?>()
情况,因此在前一种情况下处理空值时会抛出,但在后一种情况下不会。
It's clear that I can't check this via type check as reference type nullability is a compile-time feature.很明显,我无法通过类型检查来检查这一点,因为引用类型可为空性是一个编译时功能。
How could I do this?我怎么能这样做? Is it possible at all?
有可能吗?
Update更新
It seems that my intention is not clear so I'd go into greater details.似乎我的意图不清楚,所以我会更详细地介绍。
I have some code that produces values.我有一些产生值的代码。 Sometimes it may produce nulls.
有时它可能会产生空值。 And I want to give user of my code ability to decide whether he wants to get nulls from my code or no.
我想让我的代码用户能够决定他是否想从我的代码中获取空值。
With nullable structs it does work just fine:对于可为空的结构,它确实可以正常工作:
int noNullsForThisVariable = MyFunc<int>();
int? nullsAreOkHere = MyFunc<int?>();
I want to provide same behaviour for reference types now.我现在想为引用类型提供相同的行为。
There might be a missunderstanding.可能有误会。
The non-nullable reference types eg string (instead of string?) only exist at design time.不可为空的引用类型,例如字符串(而不是字符串?)仅在设计时存在。 At Runtime string is nullable, no matter if you just wrote string instead of string?.
在运行时字符串是可以为空的,不管你是不是只写了 string 而不是 string?。 With that being clarified, the question might be answered.
弄清楚了这一点,问题就可以得到解答。 In terms of nullability, nothing has changed with c# 8.
在可空性方面,c# 8 没有任何改变。
Let me explain why your approach is not possible for reference types at all.让我解释一下为什么您的方法根本不适用于引用类型。 (at least until c# 8. this behavior might change in future c# versions)
(至少在 c# 8 之前。这种行为可能会在未来的 c# 版本中改变)
Because reference types are always nullable at runtime, there is not difference in the Type itself.因为引用类型在运行时总是可以为空的,所以 Type 本身没有区别。
this is probably why you can't do: typeof(string?) You'll get an error like: "typeof cannot be used for nullable reference types"这可能就是你不能这样做的原因: typeof(string?) 你会得到一个错误,比如:“typeof cannot be used for nullable reference types”
But that doesn't neccessarily mean that the compile doesn't add a distinguishable attribute or something similar.但这并不一定意味着编译不会添加可区分的属性或类似的东西。 (which indeed could be)
(确实可能是)
But we can say, if GetType() of both type of strings will result in the same type instance, this canno be a different type at all.但是我们可以说,如果两种类型的字符串的 GetType() 都会产生相同的类型实例,那么这根本不可能是不同的类型。
Check it yourself with the following Code.使用以下代码自行检查。
string nonNullableString = "3434";
string? nullableString = "3434";
var nnStringType = nonNullableString.GetType();
var stringType = nullableString.GetType();
var isEqual = nnStringType == stringType; // true
if(object.ReferenceEquals(nnStringType, stringType)) // true
Debug.Print("it's the same object");
Nullable and non nullable string are of the same type.可为空和不可为空的字符串属于同一类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.