如何在“可能”和“可能”之间切换?对象的类型?

发布于 2024-11-06 07:05:50 字数 536 浏览 4 评论 0 原文

可能的重复:
C# - 有更好的吗除了“打开类型”之外还有其他选择吗?

我公司的遗留代码如下所示。

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

    // if obj is blah blah blah
}

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

我该如何重构这个?

谢谢。

Possible Duplicate:
C# - Is there a better alternative than this to ‘switch on type’?

My company legacy code has something as follow

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

    // if obj is blah blah blah
}

This method is just ugly. I want to refactor it, but I don't know a technique to iterate over "possible" types that obj can be.

How can I refactor this?

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

薔薇婲 2024-11-13 07:05:50

有几个选项:

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

    public Uri GetUri(动态对象)
    {
        返回 GetUriImpl(obj);
    }
    
    private Uri GetUriImpl(入口入口)
    {
        ...
    }
    
    private Uri GetUriImpl(EntryComment 评论)
    {
        ...
    }
    

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

  • 您可以创建一个Dictionary>

    私有静态字典<类型,Func<对象,Uri>> UriProvider = 
        new Dictionary>; {   
        { typeof(Entry), value =>; ... },
        { typeof(EntryComment), value =>; ... },
        { typeof(博客), value =>; ... },
    };
    

    然后:

    public Uri GetUri(object obj)
    {
        Func<对象,Uri>提供者;
        if (!UriProviders.TryGetValue(obj.GetType(), out 提供程序))
        {
            // 处理未知类型的情况
        }
        返回提供者(obj);
    }
    

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

请注意,这不会涵盖您收到 Entry 子类型等 这些特别好,介意你...我怀疑更高级别的重新设计可能更好。

A couple of options:

  • If you're using C# 4, you could use dynamic typing, and split the method into a number of overloads:

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

    In this case you'd probably want some sort of "backstop" method in case it's not a known type.

  • You could create a 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 => ... },
    };
    

    and then:

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

    Note that this won't cover the case where you receive a subtype of Entry etc.

Neither of these are particularly nice, mind you... I suspect a higher level redesign may be preferable.

听,心雨的声音 2024-11-13 07:05:50

您还可以使用接口重构它

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 
}

You can also refactor this with interfaces

public interface IHasUri
{
   public Uri GetUri();
}

and implement this interface in all you hierarchy. Than you can use

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

    // bla bla bla 
}
一城柳絮吹成雪 2024-11-13 07:05:50

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

你可以创建一个像 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;

I think Lasse V. Karlsen has the right of it in his comments, a redesign is more appropriate perhaps

You could create an interface like Stecya suggests

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

and then for each object that you care for, eg Entry, you could

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

and now you can just call it on the object

var entry = new Entry();
var uri = entry.Url;
鹤仙姿 2024-11-13 07:05:50

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

You can have a List<Type>() with all types you want to check for and iterate that list. but I don't think that makes the code faster.

那请放手 2024-11-13 07:05:50

您无法switch-case 类型。

switch 表达式或 case 标签必须是 bool、char、string、整型、枚举或相应的可为空类型

You can't switch-case types.

A switch expression or case label must be a bool, char, string, integral, enum, or corresponding nullable type

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文