【问题标题】:C#10 - using the type T to switch in a generic methodC#10 - 使用类型 T 切换泛型方法
【发布时间】:2021-11-09 21:49:21
【问题描述】:

关于如何在旧版本的 C# 中打开类型有很多答案。我的问题与如何打开泛型方法中调用的类型有关:

    public T GetAxis<T>(object axisObject)
    {
        switch (typeof(T))
        {
            case Axis:
                //...do something
                break;
        }

        return null;
    }

我收到一条错误消息:

case Axis axis:

错误是:

“System.Type”类型的表达式无法由“MyNamespace.Axis”类型的模式处理。

我相信我的问题是如何在 规范中调用类型,以便我可以打开它。

【问题讨论】:

  • 好吧,老实说:如果您打开 T,它并不是真正的通用 - 但是:if (typeof(T) == typeof(Axis)) {...} 也许?或者创建一个字典,将Type 映射到一些预期类型的​​枚举,然后打开它?
  • 您是真正尝试打开通用T,还是尝试打开axisObject 的类型?
  • 您为什么要这样做?真的do something应该由那个类型定义,所以你可以只约束T来实现一个方法void DoSomething()

标签: c# reflection switch-statement c#-10.0


【解决方案1】:

较新版本的 C# 没有添加任何专门围绕打开 Type 值的功能。如果您真的尝试基于泛型类型进行切换,您可能需要遵循其他 SO 帖子中推荐的模式。

但是,可能有比使用泛型类型更好的方法。您尝试在该类型上 switch 的事实意味着您希望代码在调用您的方法时使用的类型有限。在这种情况下,您最好为每种类型显式使用不同的方法。

代替:

var axis = GetAxis<Axis>(axisObject);
var somethingElse = GetAxis<SomethingElse>(axisObject);

用途:

var axis = GetAxis(axisObject);
var somethingElse = GetSomethingElse(axisObject);

您的示例似乎没有这样做,但如果您真的试图关闭的是传入对象的类型,那么新版本的 C# do 通过模式匹配提供一些更好的选择。例如:

public T GetAxis<T>(object axisObject)
{
    switch (axisObject)
    {
        case Axis axis:
            //...do something with `axis`
            break;
        case SomethingElse somethingElse:
            //...do something with `somethingElse`
            break;
    }

    return default;
}

在最后一种情况下,我不清楚 T 泛型类型具有什么值:您可以将其替换为非泛型返回类型。

【讨论】:

    【解决方案2】:

    在处理这类事情时,我倾向于求助于以下字典:

    private Dictionary<Type, Delegate> _axisCases = new Dictionary<Type, Delegate>();
    

    你可以围绕它编写这样的代码:

    public class MyCode
    {
        public MyCode()
        {
            this.SetCase<Axis>(o => new Axis());
        }
        
        private Dictionary<Type, Delegate> _axisCases = new Dictionary<Type, Delegate>();
    
        private void SetCase<T>(Func<object, T> func)
        {
            _axisCases[typeof(T)] = func;
        }
    
        public T GetAxis<T>(object axisObject) where T : class
        {
            var t = typeof(T);
            if (_axisCases.ContainsKey(t))
            {
                var func = (Func<object, T>)_axisCases[t];
                return func(axisObject);
            }
            return null;
        }
    }
    

    现在你可以这样称呼它:

    var myCode = new MyCode();
    var axis = myCode.GetAxis<Axis>(new object());
    

    这种类型的代码是最灵活的。但是,如果您想要更接近普通案例陈述的内容

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多