开发者

How to switch between "possible" type of an object? [duplicate]

This question already has answers here: Closed 10 years ago开发者_开发问答.

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.


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.


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 
}


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;


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.


You can't switch-case types.

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜