【问题标题】:Can I use pattern matching for code like this (on generic types) [duplicate]我可以对这样的代码使用模式匹配吗(在泛型上)[重复]
【发布时间】:2020-01-10 18:39:36
【问题描述】:

我想使用模式匹配来替换多个if 语句,如下面的方法Select<T>() 所示。我想在typeof(T) 上使用switch() 语句。

static class Program
{
    static void Main(string[] args)
    {
        var doc = new Document();
        IWire select = doc.Select<IWire>();
    }

    public static T Select<T>(this Document document) where T : class, IGeneric
    {
        var t = typeof(T);
        if (t.IsAssignableTo(typeof(IWire)))
        {
            return document.SelectEntity(EntityType.Wire) as T;
        }
        if (t.IsAssignableTo(typeof(ISolid)))
        {
            return document.SelectEntity(EntityType.Solid) as T;
        }
        if (t.IsAssignableTo(typeof(ISurface)))
        {
            return document.SelectEntity(EntityType.Surface) as T;
        }
        // imagine a lot of if statements here
        return null;
    }
}

public enum EntityType
{
    Wire,
    Surface,
    Solid
}

public interface IGeneric
{
}

public interface IWire : IGeneric
{
}
public interface ISurface : IGeneric
{
}
public interface ISolid : IGeneric
{
}

public class Document
{
    public IGeneric SelectEntity(EntityType entity)
    {
        throw new NotImplementedException();
    }
}

我看到的所有示例都在switch(thing) 语句中使用了一个instance,并且像下面这样的代码显然是错误的

switch(typeof(T))
{
    case // what here?
}

【问题讨论】:

  • 你能分享剩下的代码和最小的可重现样本吗?实际上,类型模式匹配是在 c# 7 中添加的
  • 还有两个相关的GitHub线程,switch on System.Typepattern match via generic constraint
  • @PavelAnikhouski - 我制作了一个 mcve 来展示这个问题。
  • 其实this answerSwitching on type with a generic return type 完全回答了你的问题吗?
  • @ja72 - 是的,答案指出目前还没有实现一个漂亮的方法,指向一些开放的增强线程,并提供了一个hacky解决方法。您当前的代码看起来比解决方法恕我直言。

标签: c# generics pattern-matching c#-7.0


【解决方案1】:

所以基于cmets的答案是C#还不能做到这一点(建议herehere)。

但有一个 hack,如 https://stackoverflow.com/a/46769048/380384 所示,虽然不是完全相同的副本。

我可以使用的解决方案如下(感谢@dbc 为我指明了正确的方向)。

public static T Select<T>(this Document document) where T : class, IGeneric
{
    var t = typeof(T);
    switch (true)
    {
        case var _ when t.IsAssignableFrom(typeof(IWire)):
            return document.SelectEntity(EntityType.Wire) as T;

        case var _ when t.IsAssignableFrom(typeof(ISurface)):
            return document.SelectEntity(EntityType.Surface) as T;

        case var _ when t.IsAssignableFrom(typeof(ISolid)):
            return document.SelectEntity(EntityType.Solid) as T;

        default:
            return null;
    }

}

但就可读性和设计意图而言,它可能确实是对if 语句序列的改进。

【讨论】:

    猜你喜欢
    • 2019-06-03
    • 1970-01-01
    • 2014-10-16
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    相关资源
    最近更新 更多