如何在 C# 中的泛型类型参数中使用 Switch...Case?

2024-03-06

我有一堂课正在使用Generic Type Parameter动态地使用它。现在,我正在使用if..else这与我的自定义类配合得很好。我想知道我是否可以使用switch..case here.

如果数据类型是decimal or int那么我可以使用TypeCode像这样。

switch (Type.GetTypeCode(typeof(T)))
{
    case TypeCode.Int32:
       break;
    case TypeCode.Decimal:
       break;
}

但我有我创建的自定义类,我想使用它们。下面的代码有效并尝试使用switch..case如果可能的话。

My Code:

void LogError<T>(T response, string orderId)
{
    if (typeof(T) == typeof(QuoteResponse))
    {
        var quoteResponse = response as QuoteResponse;

        //Do something
    }
    else if (typeof(T) == typeof(CommitResponse))
    {
        var commitResponse = response as CommitResponse;

        //Do something
    }
    else if (typeof(T) == typeof(CancelResponse))
    {
        var cancelResponse = response as CancelResponse;

        //Do something
    }
    else if (typeof(T) == typeof(StatusResponse))
    {
        var statusResponse = response as StatusResponse;

        //Do something
    }
}

C# switch关于泛型类型参数的声明,i.e<T>


0.下面的代码中使用的演示类型。

class MyClass { };    struct MyStruct { };    enum MyEnum { };

1.在您的项目中全局定义一个struct具有单个泛型类型参数,如下所示。

public struct TokenOf<X> { };

3. switch陈述。这个演示展示了一个通用的method,但当然该技术也可以在通用范围内的任何地方使用class or struct:(注意这个方法使用开关表达式 https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/switch-expression语法可用于C# 8):

string GenericMethod<T>() =>
    default(TokenOf<T>) switch
    {
        TokenOf<int> _      /**/ => "II",
        TokenOf<Guid> _     /**/ => "GG",
        TokenOf<string> _   /**/ => "SS",
        TokenOf<object> _   /**/ => "OO",
        TokenOf<MyEnum> _   /**/ => "EE",
        TokenOf<MyClass> _  /**/ => "CC",
        TokenOf<MyStruct> _ /**/ => "QQ",
        _                   /**/ => "??",
    };

3a.在这些 switch 表达式示例中,您可以使用{ }而不是“丢弃符号”_以获得同等结果。这表明可爱的(或者可能是滥用的)代码格式化选项,例如:

string GenericMethod<T>() => default(TokenOf<T>) switch
{
    TokenOf<int>      /**/ _ => "II",
    TokenOf<Guid>     /**/ _ => "GG",
    // etc...
    TokenOf<MyStruct> /**/ _ => "QQ",
    {                 /**/ } => "??",
};

4.演示测试代码

void switch_on_generic_type() =>
    Console.WriteLine($@"{
        GenericMethod<int>()}   {
        GenericMethod<Guid>()}   {
        GenericMethod<string>()}   {
        GenericMethod<object>()}   {
        GenericMethod<MyEnum>()}   {
        GenericMethod<MyClass>()}   {
        GenericMethod<MyStruct>()}   {
        GenericMethod<double>()}");
    }

5.演示的输出

II GG SS OO EE CC QQ ??


6.讨论

该技术利用了 .NET 值类型永远无法实例化这一事实。由此可见,值类型(与引用类型不同——例如,它会失去它们的值)System.Type身份如果null存储在未指定的变量中)永远不会丢失其特定身份。因此,TokenOf<>struct 保证代表不同的System.Type每个不同参数化的身份X,即使所有实例始终都是“默认”实例(实际上大小为 1 字节)。的泛型类型参数struct区分它们是必要且充分的。

为了清楚起见,请注意,虽然TokenOf<>所以must be a struct,切换后的泛型类型参数<X>可以是任何有效的 .NET 类型。而事实上,如果X保证代表一个值类型,你甚至不需要TokenOf<>根本没有包装。例如,考虑带有类型参数的泛型类或方法T受限于unmanaged (or struct) 关键字。在这种情况下,上面的 (3.) 等示例将简化为:

string GenericMethod<T>() where T : unmanaged =>
    default(T) switch
    {
        int _      /**/ => "II",
        Guid _     /**/ => "GG",
        MyEnum _   /**/ => "EE",
        MyStruct _ /**/ => "QQ",
        TimeSpan _ /**/ => "TS",
        _          /**/ => "??",
    };

The typeof(T)运算符在本页的其他答案中使用,但因为它(根据定义)体现了具体化 https://en.wikipedia.org/wiki/Reification_(computer_science)#Reflective_programming_languages操作于T这对于静态分析来说本质上是不透明的,并且在本质上是被硬阻止的System.Type https://learn.microsoft.com/en-us/dotnet/api/system.type?view=netframework-4.8实例(显然,它本身只能在运行时存在)我认为它是一个非常生硬和戏剧性的工具。

通过避免typeof,这里展示的技术可能对编译器、优化器、分析器和其他工具更友好CTS https://en.wikipedia.org/wiki/Common_Type_System 离线元数据 https://en.wikipedia.org/wiki/Metadata_(CLI)系统(待调查)。最重要的是,习惯国际法制度放宽了过度强制的规定System.Type实例化(通过typeof)可能对 JIT 有利。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 C# 中的泛型类型参数中使用 Switch...Case? 的相关文章

  • Qt - QProcess 不工作

    我尝试启动 Internet Explorer 所以我使用下面的代码 QProcess process new QProcess this QString temp C Program Files Internet Explorer iex
  • Rx.NET 中是否有一个Subject 实现,其功能类似于BehaviourSubject,但仅在值发生更改时才发出?

    有没有Subject https learn microsoft com en us previous versions dotnet reactive extensions hh229699 v vs 103 Rx NET 中的实现在功能
  • 当事件button.click发生时,如何获取按钮名称/标签?

    我以编程方式制作按钮并将它们添加到堆栈面板中 以便每次用户导航到页面时按钮都会发生变化 我正在尝试做这样的事情 当我单击创建的按钮时 它将获取按钮的标签并转到正确的页面 但是 我无法使用 RoutedEventHandler 访问按钮元素
  • 如何使用 Regex.Replace 从字符串中删除数字?

    我需要使用Regex Replace从字符串中删除所有数字和符号 输入示例 123 abcd33输出示例 abcd 请尝试以下操作 var output Regex Replace input d string Empty The d标识符
  • 如何将AVFrame转换为glTexImage2D使用的纹理?

    如您所知 AVFrame 有 2 个属性 pFrame gt data pFrame gt linesize 当我从视频 sdcard test mp4 android平台 读取帧后 并将其转换为RGB AVFrame副 img conve
  • 在 .NET MAUI 中实现 TouchTracking

    我一直致力于将我们的应用程序从 Xamarin Forms 迁移到 NET MAUI 我们的应用程序几乎没有绘图功能 用户可以用手指进行绘图 我们用了TouchTrackingXamarin Forms 中的 nuget 包 但与 NET
  • 如果输入被重定向则执行操作

    我想知道如果我的输入被重定向 我应该如何在 C 程序中执行操作 例如 假设我有已编译的程序 prog 并且我将输入 input txt 重定向到它 我这样做 prog lt input txt 我如何在代码中检测到这一点 一般来说 您无法判
  • 不可变类与结构

    以下是类与 C 中的结构的唯一区别 如果我错了 请纠正我 类变量是引用 而结构变量是值 因此在赋值和参数传递中复制结构的整个值 类变量是存储在堆栈上的指针 指向堆上的内存 而结构变量作为值存储在堆上 假设我有一个不可变的结构 该结构的字段一
  • 在 C# 中为父窗体中的子窗体控件添加事件处理程序

    我有两种形式 一种是带有按钮和文本框的父表单 单击该按钮时 将打开一个对话框 该子窗体又包含一个文本框和一个按钮 现在我想要的是 每当子表单文本框中的文本更改时 父表单文本框中的文本会自动更改 为了获得这个 我所做的是 Form3 f3 n
  • 在 C 中使用枚举而不是 #defines 作为编译时常量是否合理?

    在 C 工作了一段时间后 我将回到 C 开发领域 我已经意识到 在不必要的时候应该避免使用宏 以便让编译器在编译时为您做更多的工作 因此 对于常量值 在 C 中我将使用静态 const 变量或 C 11 枚举类来实现良好的作用域 在 C 中
  • C++ - 多维数组

    处理多维数组时 是否可以为数组分配两种不同的变量类型 例如你有数组int example i j 有可能吗i and j是两种完全不同的变量类型 例如 int 和 string 听起来您正在寻找 std vector
  • 将 Word 转换为 PDF - 禁用“保存”对话框

    我有一个用 C 编写的 Word 到 PDF 转换器 除了一件事之外 它工作得很好 有时 在某些 Word 文件上 后台会出现一条消息保存源文件中的更改 gt 是 否 取消 但我没有对源文件进行任何更改 我只想从 Word 文件创建 PDF
  • 将函数参数类型提取为参数包

    这是一个后续问题 解包 元组以调用匹配的函数指针 https stackoverflow com questions 7858817 unpacking a tuple to call a matching function pointer
  • 比较:接口方法、虚方法、抽象方法

    它们各自的优点和缺点是什么 接口方法 虚拟方法 抽象方法 什么时候应该选择什么 做出这一决定时应牢记哪些要点 虚拟和抽象几乎是一样的 虚方法在基类中有一个实现 可以选择重写 而抽象方法则没有 并且must在子类中被覆盖 否则它们是相同的 在
  • 模板类中的无效数据类型生成编译时错误?

    我正在使用 C 创建一个字符串类 我希望该类仅接受数据类型 char 和 wchar t 并且我希望编译器在编译时使用 error 捕获任何无效数据类型 我不喜欢使用assert 我怎样才能做到这一点 您可以使用静态断言 促进提供一个 ht
  • 使动态创建的链接标签在 Winforms 中可点击

    我正在制作一个程序 允许用户单击由动态链接标签创建的公司名称 在我想知道如何做到这一点之前 我从未在 C 中使用过链接标签 可为特定用户生成的业务数量各不相同 因此每个用户的链接标签数量并不相同 然后我想捕获业务 ID 以进行 Json 调
  • 如何解压 msgpack 文件?

    我正在将 msgpack 编码的数据写入文件 在编写时 我只是使用 C API 的 fbuffer 如 我为示例删除了所有错误处理 FILE fp fopen filename ab msgpack packer pk msgpack pa
  • C++:为什么 numeric_limits 对它不知道的类型起作用?

    我创建了自己的类型 没有任何比较器 也没有专门化std numeric limits 尽管如此 由于某种原因 std numeric limits
  • 为什么空循环使用如此多的处理器时间?

    如果我的代码中有一个空的 while 循环 例如 while true 它将把处理器的使用率提高到大约 25 但是 如果我执行以下操作 while true Sleep 1 它只会使用大约1 那么这是为什么呢 更新 感谢所有精彩的回复 但我
  • 在 System.Type 上使用条件断点时出错

    这是函数 public void Init System Type Type this Type Type BuildFieldAttributes BuildDataColumns FieldAttributes 我在第一行设置了一个断点

随机推荐

  • Paypal订阅付款错误消息3005

    我正在尝试贝宝定期付款并使用此表格 表单操作 名称 xclick subscriptions 方法 post gt 登录paypal付款时出现错误消息 抱歉 您的上一个操作无法完成 如果您要进行购买或汇款 我们建议您在 30 分钟后检查您的
  • Python:将 pandas Dataframe 作为参数传递给子进程

    如何使用子进程通过 Spark Submit 将数据帧作为参数发送到 Python 脚本 我已经尝试了下面的代码 但没有成功 因为我们无法连接字符串和对象 def spark submit self test cases email com
  • 将 2 个像素点在一起

    我在第一个像素的右边点了一个像素 但结果不同 第二个像素距离第一个像素很远 怎么了 org 100h change to 320x200 graphic mode mov ax 13 int 10h frame buffer locatio
  • 使用云端点进行对象化

    我正在使用 appengine 云端点和 objectify 我之前已经部署过这些端点 现在我正在更新它们 但它无法与 Objectify 一起使用 我已经搬到一台新机器并运行最新的 appengine 1 8 6 尝试将 objectif
  • FCM 成功,但 Android 设备未收到通知

    当我尝试通过 cURL 请求发送推送通知时 服务器的响应表明我已成功 但设备上未收到消息 我已经尝试过使用多播和单接收者有效负载 这是我的 PHP 代码
  • Django:将“相同父级”约束应用于映射到自身的ManyToManyField

    我有一个模型 其中任务是一项工作 每项工作都可能依赖于一些其他任务的完成才能开始 任务被分组为作业 我想禁止作业之间的依赖关系 这是我的模型的相关子集 class Job models Model name models CharField
  • 设备显示设置(Android 屏幕缩放和字体)

    我的任务是与我们现有的 IOS 应用程序一起完成一个 Andoid 应用程序 Android 的项目框架已经存在 我只需要填补空白即可使其与 IOS 版本保持同步 我一直在通过自己的手机进行测试 并且一直在为 Galaxy S6 上的字体太
  • ReactJS:css 转换在 componentDidMount 中不起作用

    当 的时候EffectBox组件已安装 我想添加一个show class到这个组件 但是 css 过渡不起作用 这是js代码 var EffectBox React createClass componentDidMount functio
  • FC++ 是否被任何开源项目使用?

    The FC http www cc gatech edu yannis fc 库提供了一种有趣的方法来支持 C 中的函数式编程概念 一个简短的例子来自FAQ http www cc gatech edu yannis fc faq htm
  • 从 Pandas 中的过滤结果创建布尔掩码[重复]

    这个问题在这里已经有答案了 我知道如何在查询单列时创建掩码来过滤数据帧 import pandas as pd import datetime index pd date range 2013 1 1 periods 100 freq 30
  • Google Analytics - 跟踪多个网站(顶级域)

    我有 10 个顶级域名 例如example1 com example2 com example3 com 等 每个域都有自己独特的网站 不是重定向 我的目标是为所有 10 个网站拥有一个 Google Analytics 帐户和一个网络资产
  • 如何在 Java 中仅从月份和年份生成日期?

    我需要为信用卡到期日期生成一个新的 Date 对象 我只有一个月和一年 如何根据这两个生成日期 我需要尽可能最简单的方法 我在这里阅读了其他一些答案 但它们似乎都太复杂了 你可以使用java util Calendar Calendar c
  • 如何使用vba仅将单个工作表复制到另一个工作簿

    我有 1WorkBook SOURCE 包含大约 20 张 我只想将一张特定的工作表复制到另一张工作表Workbook TARGET 使用 Excel VBA 请注意 TARGET 工作簿尚不存在 它应该在运行时创建 使用的方法 1 Act
  • 将 jhipster 应用程序部署到不同的上下文路径

    我正在尝试使用 mvn 命令部署 jhipster 应用程序 我相信这将运行默认的 spring boot run 我认为这会部署到tomcat 服务器启动后 应用程序即可在http 本地主机 8080 http localhost 808
  • 如何确定 32 位 IEEE 浮点值中的集合 S 中有多少个整数 [重复]

    这个问题在这里已经有答案了 有人能给我解释一下它到底在说什么吗 我知道这基本上意味着它是单精度 具有 1 位符号 8 位指数和 23 位尾数 答案不应该是 2 2 8 2 2 23 吗 编辑 2 2 8 2 2 23 是否确定所有 32 位
  • Docker:向已创建的容器添加重启策略

    我看到 Docker 添加了一些称为重新启动策略的内容来处理容器的重新启动 例如重新启动 虽然这非常有用 但我发现重新启动策略命令只能与docker run并不是docker start 所以我的问题是 有什么方法可以将重新启动策略添加到过
  • 实体化滚动体

    我在设置时遇到问题tbody高度宽度overflow y scroll 我尝试过这个CSS table status sheet tbody min height 300px overflow y auto 这是我的表代码 div clas
  • 如何在 JavaScript 中给出变量引用?

    我想在javascript中给出变量引用 例如 我想做 a 1 b a a 2 且有b 2 并相应地改变为a 这在 JavaScript 中可能吗 如果不是 有没有办法像 a onchange function b a 那样 我想做的是创建
  • 在 React Native 和 Android 之间共享 Realm 实例

    我正在开发一个 React Native 项目 该项目使用 Realm for React Native 它工作没有问题 但现在 我面临着编写使用相同 Realm 实例的 Android 服务的问题 这可能吗 我该怎么做 我认为你可以通过以
  • 如何在 C# 中的泛型类型参数中使用 Switch...Case?

    我有一堂课正在使用Generic Type Parameter动态地使用它 现在 我正在使用if else这与我的自定义类配合得很好 我想知道我是否可以使用switch case here 如果数据类型是decimal or int那么我可