英文:
take nullable and return non-nullable reference and value types in single method
问题
Sure, here's the translated code:
我想要一个方法,它接受一个可空类型并返回一个非可空类型。它可以是值类型或引用类型。我似乎只能通过拥有2个方法来实现这个:
public static T Do<T>(
T? t
) where T: struct
{
return t == null ? throw new Exception("") : t.Value;
}
public static T Do<T>(
T? t
) where T : class
{
return t == null ? throw new Exception("") : t;
}
这个代码可以被翻译成中文如上所示。
英文:
i want a method that takes a nullable and returns nonnullable. it can be value or ref type. i only seem to be able to do this by having2 methods:
public static T Do<T>(
T? t
) where T: struct
{
return t == null ? throw new Exception("") : t.Value;
}
public static T Do<T>(
T? t
) where T : class
{
return t == null ? throw new Exception("") : t;
}
is there a way to do this with a single method?
答案1
得分: 2
抱歉,以下是翻译好的部分:
"不幸的是,你不能使用单一方法来实现这个。"
"因为对于值类型 'TValueType' 上的 ?
注释实际上是 C# 语法糖,表示 .NET 类型 Nullable<TValueType>
。但对于引用类型 'TRefType',?
注释 'TRefType?' 并不改变带注释的类型,它仍然只是类型 TRefType;这里的 ?
只是静态代码分析的元数据注释。"
"所以,忽略静态代码分析的元数据,你的代码等效于:"
public static T Do<T>(
Nullable<T> t
) where T: struct
{
return t == null ? throw new Exception("") : t.Value;
}
public static T Do<T>(
T t
) where T : class
{
return t == null ? throw new Exception("") : t;
}
"现在应该明显了,你不能有一个参数既是 'Nullable<T>' 又不是 'Nullable<T>' 的单一方法签名..."
"那么你可能会想,一个方法如何?"
public static T Do<T>(T? t)
{
if (t is null) throw new Exception("");
... 现在呢?如何区分值类型和引用类型?
}
"但这样做将涉及到反射,用于识别给定的 'T' 是值类型还是引用类型,并为将值分派到相应的处理值类型或引用类型的代码/方法。虽然这将给你一个单一的公共方法,但代价是你的代码现在会变得更加复杂和慢。在未来的 C# 版本中,如果能够学会模式匹配一个值是值类型还是引用类型,那么进行这种反射操作很少值得麻烦,以我的看法来说。"
英文:
No, unfortunately you can't do this with a single method.
Because the ?
annotation on a value type TValueType
is actually C# syntactic sugar for the .NET type Nullable<TValueType>
. But for a reference type TRefType
, the ?
annotation TRefType?
does not change the annotated type, it's still just the type TRefType; with ?
here just being a metadata annotation for the static code analysis.
So, ignoring the static code analysis metadata, your code is equivalent to:
public static T Do<T>(
Nullable<T> t
) where T: struct
{
return t == null ? throw new Exception("") : t.Value;
}
public static T Do<T>(
T t
) where T : class
{
return t == null ? throw new Exception("") : t;
}
It should now be apparent that you can't have a single method with a signature where its parameter is both Nullable<T>
and not Nullable<T>
at the same time...
Well, you might think how about one method
public static T Do<T>(T? t)
{
if (t is null) throw new Exception("");
... and now? How to distinguish between value and reference types?
}
but doing this would involve reflection both for identifying whether a given T
is a value type or a reference type, and for dispatching the value to respective code/methods that either deal with value types or references types. While this would give you a single public method, the price is that your code would now become much more complicated and slower. Until a future C# version learns to pattern match whether a value is of a value type or a reference type, doing these kind of reflection shenanigans is seldomly worth the trouble in my opinion.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论