【问题标题】:How to switch between "possible" type of an object? [duplicate]如何在对象的“可能”类型之间切换? [复制]
【发布时间】:2011-08-22 06:50:57
【问题描述】:

可能重复:
C# - Is there a better alternative than this to ‘switch on type’?

我的公司遗留代码如下

public override Uri GetUri(object obj)
{
    if ((obj is Entry) || (obj is EntryComment))
    {
        //
    }
    if (obj is Blog)
    {
        //
    }

    // if obj is blah blah blah
}

这种方法很丑。我想重构它,但我不知道迭代 obj 可能是的“可能”类型的技术。

我该如何重构它?

谢谢。

【问题讨论】:

标签: c# .net types switch-statement


【解决方案1】:

几个选项:

  • 如果您使用的是 C# 4,则可以使用动态类型,并将方法拆分为多个重载:

    public Uri GetUri(dynamic obj)
    {
        return GetUriImpl(obj);
    }
    
    private Uri GetUriImpl(Entry entry)
    {
        ...
    }
    
    private Uri GetUriImpl(EntryComment comment)
    {
        ...
    }
    

    在这种情况下,您可能需要某种“支持”方法,以防它不是已知类型。

  • 你可以创建一个Dictionary<Type, Func<object, Uri>>:

    private static Dictionary<Type, Func<object, Uri>> UriProviders = 
        new Dictionary<Type, Func<object, Uri>> {   
        { typeof(Entry), value => ... },
        { typeof(EntryComment), value => ... },
        { typeof(Blog), value => ... },
    };
    

    然后:

    public Uri GetUri(object obj)
    {
        Func<object, Uri> provider;
        if (!UriProviders.TryGetValue(obj.GetType(), out provider))
        {
            // Handle unknown type case
        }
        return provider(obj);
    }
    

    请注意,这不会涵盖您收到Entry 等子类型的情况。

请注意,这些都不是特别好...我怀疑更高级别的重新设计可能更可取。

【讨论】:

  • +1,仅回答实际显示如何操作且不违反开放/封闭原则的答案
【解决方案2】:

你也可以用接口重构它

public interface IHasUri
{
   public Uri GetUri();
}

并在所有层次结构中实现此接口。比你可以使用

public Uri GetUri(object obj)
{
    IHasUri hasUri = obj as IHasUri;
    if(hasUri != null)
      Uri uri = hasUri.GetUri();

    // bla bla bla 
}

【讨论】:

    【解决方案3】:

    我认为 Lasse V. Karlsen 在他的 cmets 中拥有它的权利,也许重新设计更合适

    你可以像 Stecya 建议的那样创建一个界面

    public interface IUriAccessible { //or some sort of a more descriptive name
        Uri Url {get;}
    }
    

    然后对于您关心的每个对象,例如Entry,您可以

    public class Entry:IUriAccessible {
        //... other code here
        public Uri Url {
            get {
                //return uri here
            }
        }
    }
    

    现在你可以在对象上调用它

    var entry = new Entry();
    var uri = entry.Url;
    

    【讨论】:

      【解决方案4】:

      您可以拥有一个List&lt;Type&gt;(),其中包含您想要检查并迭代该列表的所有类型。但我不认为这会使代码更快。

      【讨论】:

      • 我不想要“更快”的代码,而是“更易读”的代码:)。问题是,每种类型的处理代码都不一样,所以我觉得 List 不合适。 Switch是更合适的选择
      【解决方案5】:

      你不能switch-case 类型。

      switch 表达式或 case 标签必须是 bool、char、string、integral、enum 或相应的可为 null 类型

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-02
        • 1970-01-01
        • 2016-09-10
        • 1970-01-01
        • 2019-03-14
        • 2014-12-28
        • 2022-11-01
        • 1970-01-01
        相关资源
        最近更新 更多