繁体   English   中英

如何检查是否使用可为空的泛型参数调用泛型函数

How to check if generic function is called with nullable generic argument

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我正在尝试编写一个泛型函数,该函数的行为取决于是否使用允许空值的参数调用它。 在 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;
}

其中AcceptsNulls()是这样的:

public static bool IsAcceptNulls(this Type type)
{
  if (type.IsValueType)
  {
    if (Nullable.GetUnderlyingType(type) != null)
    {
      return true;
    }
    return false;
  }
  return true;
}

因此, MyFunc对引用类型和值类型都能很好地工作,并适当支持可为空值类型。

但现在我想将它放在一个启用可空引用类型的代码中。 而且我希望它能够区分MyFunc<object>()MyFunc<object?>()情况,因此在前一种情况下处理空值时会抛出,但在后一种情况下不会。

很明显,我无法通过类型检查来检查这一点,因为引用类型可为空性是一个编译时功能。

我怎么能这样做? 有可能吗?


更新

似乎我的意图不清楚,所以我会更详细地介绍。

我有一些产生值的代码。 有时它可能会产生空值。 我想让我的代码用户能够决定他是否想从我的代码中获取空值。

对于可为空的结构,它确实可以正常工作:


int noNullsForThisVariable = MyFunc<int>();

int? nullsAreOkHere = MyFunc<int?>();

我现在想为引用类型提供相同的行为。

2 个回复

可能有误会。

不可为空的引用类型,例如字符串(而不是字符串?)仅在设计时存在。 在运行时字符串是可以为空的,不管你是不是只写了 string 而不是 string?。 弄清楚了这一点,问题就可以得到解答。 在可空性方面,c# 8 没有任何改变。

让我解释一下为什么您的方法根本不适用于引用类型。 (至少在 c# 8 之前。这种行为可能会在未来的 c# 版本中改变)

因为引用类型在运行时总是可以为空的,所以 Type 本身没有区别。

这可能就是你不能这样做的原因: typeof(string?) 你会得到一个错误,比如:“typeof cannot be used for nullable reference types”

但这并不一定意味着编译不会添加可区分的属性或类似的东西。 (确实可能是)

但是我们可以说,如果两种类型的字符串的 GetType() 都会产生相同的类型实例,那么这根本不可能是不同的类型。

使用以下代码自行检查。

    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");

可为空和不可为空的字符串属于同一类型。

1 如何调用没有参数的泛型函数?

向Array添加扩展,返回第一个Int或String很简单: 我可以定义一个通用版本,但我无法弄清楚如何调用它,因为它不带任何参数。 没有参数,我无法指定类型! 我可以通过添加一个虚拟参数来解决它,但这很难看。 如果有人能告诉我如何调用firstValueOfType函 ...

4 泛型函数参数

我目前正在制作新的Twig扩展程序。 此Twig扩展接受实体对象(\\AppBundle\\Entity\\*)和参数名称作为参数。 我想做的是在$entity上创建一个类型,该类型将成为Appbundle\\Entity中的类之一(可以是任何一个),并让Symfony猜测它是哪个。 ...

6 为使用参数调用泛型函数实现超时

我试图弄清楚使用Action委托类型来强制在第三方COM dll中调用的方法挂起时超时。 经过大量搜索之后,我发现我可以使用Action &lt;&gt;或Func &lt;&gt;并最多传递4个通用参数,具体取决于所调用的方法是否返回参数。 对于此实例,我希望在一系列返回void并采用 ...

9 不带参数调用泛型函数

我有一个不带参数的通用函数baz并且想从另一个成员函数helper调用它。 我想在调用函数时指定类型。 我尝试做baz&lt;T&gt;()但这没有编译。 我能够让它编译的唯一方法是这样的: 这是如何编译的? baz返回的是什么类型? 我来自 C++ 背景 BTW。 ...

10 使用varargs参数调用C ++泛型函数

在我的项目中,我有不同类型的输入参数数量不同的函数。 由于这些函数是库的一部分,我无法更改它们的定义或主体。 在我的项目中,我需要一个方法,它将接收其中一个函数的地址。 此外,它接收格式良好的参数列表(适合第一个参数中的函数)。 然后,此方法必须使用传递的参数调用传递的函数。 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM