可能重复:
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可能的“可能”类型的技术。
我该如何重构这个?
谢谢。
答案 0 :(得分:5)
有两种选择:
如果您使用的是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 :(得分:4)
您还可以使用接口
重构此内容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
}
答案 2 :(得分:1)
我认为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;
答案 3 :(得分:0)
您可以拥有一个List<Type>()
,其中包含您要检查的所有类型并迭代该列表。但我认为这不会使代码更快。
答案 4 :(得分:0)
您不能switch-case
种类型。
开关表达式或大小写标签必须是bool,char,string,integral,enum或相应的可空类型