【问题标题】:Is there a generic numeric type in C#?C# 中有通用数字类型吗?
【发布时间】:2016-06-29 12:29:22
【问题描述】:

我真的很想要一个泛型数值类型作为下面给出的Func<TInput, THere, TResult> 的第二个泛型类型参数,所以我可以在我喜欢的时候提供整数、双精度或小数。

var _resultSelectors = new Dictionary<string, Func<DateTime, /*here*/ double, DateTime>>();

// so I can do
_resultSelector.Add("foo", (DateTime dt, int x) => ...);
_resultSelector.Add("bar", (DateTime dt, double d) => ...);
_resultSelector.Add("gar", (DateTime dt, float f) => ...);
_resultSelector.Add("har", (DateTime dt, decimal d) => ...);

短:

  1. 制作自己的类型;或
  2. 使用对象并对值类型进行装箱和拆箱;或
  3. 使用dynamic 关键字,

在 C# 中是否有适当的方法来做到这一点?

我猜 Java 有一个 Number 类可能符合我的要求,但我想知道 C# 是否有类似的东西。

我想 C# 中没有这样的东西,但我想我会问一下。

【问题讨论】:

  • 如果您可能拥有全部 4 个,我建议您从 doubledecimal 中选择一个(取决于您的用例,即浮点是否合适)并将其余的转换为那个。
  • @CharlesMager 这是个好主意。
  • 没有通用接口,但您仍然会遇到根据值的运行时类型找到要调用的正确函数的问题。具体数值从何而来?
  • 非常很想将此标记为 this question 的副本。
  • @DStanley 你是对的。一个通用的INumeric&lt;in T&gt; 将是一个无限深的兔子洞。但与此同时,像简单的INumeric 这样的非通用标记界面会有什么问题?

标签: c# .net


【解决方案1】:

不,没有。泛型和算术运算(+-*/ 等)根本不能一起工作。这是一个被多次提出的问题,C# 设计委员会从未解决过(公平地说,这个功能也需要在 CLR 上工作,正如 Eric Lippert 在进一步链接的回答中指出的那样)。

奇怪的是,如果您检查 .NET Framework 的源代码,您会发现在开发的某个阶段有一个 IArithmetic&lt;T&gt; 接口,但它被废弃了;见here

您可以在SO answer 中阅读更多相关信息。

【讨论】:

    【解决方案2】:

    即使存在 包含数字类型的基本类型或接口,因为您已将约束包装在 Func 中,但它对您没有任何好处。 Func 的输入类型是逆变的,所以它的参数不能比声明的更派生。

    换句话说,你不能像用IEnumerable&lt;T&gt;那样用Func&lt;DateTime, int, DateTime&gt;替换Func&lt;DateTime, ValueType, DateTime&gt;(你可以IEnumerable&lt;int&gt;替换IEnumerable&lt;ValueType&gt;

    我认为你最好的选择是dynamic(仍然是类型安全的,但在运行时与编译时相比)或doubledecimal,如果你想做数学并且不必留在同类型。

    【讨论】:

    • Func 有差异。它的输入参数是逆变的,它的输出是协变的。这是我使用的特定重载的定义:public delegate TResult Func&lt;in T1, in T2, out TResult&gt;(T1 arg1, T2 arg2);
    • 抱歉,我再次阅读了您的消息。你是对的。由于其输入类型的逆变性,实际封闭的泛型参数不能比它们的编译时类型更多地派生。
    【解决方案3】:

    C# 10 和 .NET 6:2021 年 11 月起的解决方案

    好消息:现在 .NET 6 和 C# 10 中有一个解决方案,参见。 https://devblogs.microsoft.com/dotnet/preview-features-in-net-6-generic-math/#generic-math

    当你想要任何号码时,你可以使用INumber&lt;T&gt;。如果您需要任何特定的运算符,请使用相应的接口,例如IAdditionOperatorsa + bIIncrementOperatorsa++ 等等。

    注意:在我回答时,此功能只是一个预览。 Microsoft 将在 .NET 6 的最终版本中保留这一点,因为他们仍然希望允许突破机会。要使用该功能,必须在项目配置中启用预览功能:

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <EnablePreviewFeatures>true</EnablePreviewFeatures>
        <LangVersion>preview</LangVersion>
        <OutputType>Exe</OutputType>
        <TargetFramework>net6.0</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="System.Runtime.Experimental" Version="6.0.0-preview.7.21377.19" />
      </ItemGroup>
    
    </Project>
    

    【讨论】:

      猜你喜欢
      • 2010-11-21
      • 2023-01-16
      • 1970-01-01
      • 2013-01-20
      • 2020-05-24
      • 2016-06-19
      • 1970-01-01
      • 1970-01-01
      • 2018-05-26
      相关资源
      最近更新 更多