How to switch between "possible" type of an object? [duplicate]
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
精彩评论