将可空类型转换为非可空引用和值类型在单个方法中。

huangapple go评论63阅读模式
英文:

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&lt;T&gt;(
       T? t
    ) where T: struct
    {
        return t == null ? throw new Exception(&quot;&quot;) : t.Value;
    }

    public static T Do&lt;T&gt;(
       T? t
    ) where T : class
    {
        return t == null ? throw new Exception(&quot;&quot;) : t;
    }

is there a way to do this with a single method?

答案1

得分: 2

抱歉,以下是翻译好的部分:

"不幸的是,你不能使用单一方法来实现这个。"

"因为对于值类型 'TValueType' 上的 ? 注释实际上是 C# 语法糖,表示 .NET 类型 Nullable&lt;TValueType&gt;。但对于引用类型 'TRefType',? 注释 'TRefType?' 并不改变带注释的类型,它仍然只是类型 TRefType;这里的 ? 只是静态代码分析的元数据注释。"

"所以,忽略静态代码分析的元数据,你的代码等效于:"

public static T Do&lt;T&gt;(
   Nullable&lt;T&gt; t
) where T: struct
{
    return t == null ? throw new Exception(&quot;&quot;) : t.Value;
}

public static T Do&lt;T&gt;(
   T t
) where T : class
{
    return t == null ? throw new Exception(&quot;&quot;) : t;
}

"现在应该明显了,你不能有一个参数既是 'Nullable<T>' 又不是 'Nullable<T>' 的单一方法签名..."

"那么你可能会想,一个方法如何?"

public static T Do&lt;T&gt;(T? t)
{
    if (t is null) throw new Exception(&quot;&quot;);

    ... 现在呢?如何区分值类型和引用类型?
}

"但这样做将涉及到反射,用于识别给定的 '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&lt;TValueType&gt;. 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&lt;T&gt;(
       Nullable&lt;T&gt; t
    ) where T: struct
    {
        return t == null ? throw new Exception(&quot;&quot;) : t.Value;
    }

    public static T Do&lt;T&gt;(
       T t
    ) where T : class
    {
        return t == null ? throw new Exception(&quot;&quot;) : t;
    }

It should now be apparent that you can't have a single method with a signature where its parameter is both Nullable&lt;T&gt; and not Nullable&lt;T&gt; at the same time...

Well, you might think how about one method

public static T Do&lt;T&gt;(T? t)
{
    if (t is null) throw new Exception(&quot;&quot;);

    ... 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.

huangapple
  • 本文由 发表于 2023年6月12日 00:48:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76451523.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定