我遇到与this问题类似的问题,我只是在学习泛型,所以想要一个实用的解决方案,我的方法返回的不仅仅是int
或double
。
我有一个函数可以根据用户输入返回一个对象(来自一组彼此无关的已知类)。
例如,如果我有以下两个类
public class A
{
}
并且
public class B
{
}
我的方法是:
public Object getObject(int objType)
{
//return appropriate object based on objType (1==A, 2==B);
}
我可以在我的代码中使用if (getObject(int objType) is A)
这样的语句,但这需要很多if
语句,这不是一个好的解决方案(恕我直言)。
所以我正在寻找更好的设计解决方案来解决这个问题。有什么建议吗?
修改
我需要使用返回的对象一段时间,可能还需要将其传递给其他方法或返回它的引用。所以期待一些移动到那个对象。在建议解决这个问题的方法时,请记住这一点。
答案 0 :(得分:1)
开关/箱体怎么办?
public Object getObject(int objType)
{
switch( objType )
{
case 1: return new A();
case 2: return new B();
}
}
请注意,这与generics一样 nothing 。
修改强>
阅读完评论后,我发现这根本不是你需要的。根据新的信息,我看到只有两种方法可以(稍微)得到你需要的东西。
A
和B
都继承的基类(在这种情况下让我们称之为C
),并使getObject
方法返回C的对象。public T getObject<T>()
。这意味着调用者必须将对象类型而不是1或2发送到getObject
方法中,但至少他知道他将得到什么作为回报。 只要该方法返回object
,并且仅使用int
的参数来决定要创建哪种类型的对象,就无法找到您获得的对象类型返回检查对象本身,如果有很多类型的对象可以返回,那么这种代码很快就会变得混乱。
答案 1 :(得分:1)
根据某些输入声音构建不同类型的对象,就像使用Factory设计模式一样。
编辑:如果您希望调用者不检查对象类型,那么Factory模式正在成为可行的选项,因为它利用了polimorphism。将实际对象返回到基类类型的变量中,当您调用方法时,将根据实际对象类型运行正确的代码。
如果你的类型是不相关的,那么看看你是否可以让它们共享一个基类是值得的,因为使用polimorphism比解决问题更能解决问题。
答案 2 :(得分:0)
如果我有一个必须返回一个对象的类,并且我必须从一个特殊类型获取它,我通常在一个像Dictionary<Type, Func<Type>>
这样的字典中有一组工厂函数(可能有{{1}这样的参数然后我编写这些函数并将它们放入字典中。然后你可以轻松地从中获取正确的对象。
另一种方法(如果您可以访问对象的源代码并且它们有共享内容),您可以向它们添加一个接口,然后创建一个Func<P1, P2, ..., Type>
。如果您的对象的顺序正确(如果您想使用List<MyInterface>
),则只需拨打int objType
即可获得正确的对象。
答案 3 :(得分:0)
如果您只想获取提供程序类的新实例,则可以使用此函数。
public T GetObject<T>() where T : new()
{
return new T();
}
无需提及objectType
答案 4 :(得分:0)
仅供参考,您正在实施一种Factory pattern。
通常,在处理改变类型行为的函数时,只有两种方法可以避免切换:
在您的示例中,对工厂的输入是完全不相关的类型,因此您不能使用多态。
如果您可以要求用户传入一些自定义类型,那么您可以利用工厂中的多态性:
public class Selection
{
public abstract object Select();
}
public class SelectionA : Selection
{
public override object Select()
{
return new A();
}
}
public class SelectionB : Selection
{
public override object Select()
{
return new B();
}
}
// ...
public Object getObject(Selection selection)
{
return selection.Select();
}
如果A
和B
彼此相似,那么您真的应该为它们创建一个公共基类,或者如果您无法触及该代码,请使用Adapter模式,使另外3个类,具有正确的层次结构。
如果它们彼此不相似,并且您必须int
作为工厂方法的输入,那么交换机,if / else-if链或字典是您唯一的选择:
public Object getObject(int objType)
{
switch(objType)
{
// etc
}
}
或者
public Object getObject(int objType)
{
if(objType == 1)
return new A();
// etc
}
或者
public Object getObject(int objType)
{
var mapping = new Dictionary<int, Type>()
{
{ 1, typeof(A) },
{ 2, typeof(B) },
};
// use reflections to instantiate based on type
if(!mapping.ContainsKey(objType))
throw new ArgumentException("Invalid type ID specified", "objType");
System.Activator.CreateInstance(mapping[objType]);
}
答案 5 :(得分:0)
你的方法有什么不好 - 无论如何客户端代码应该知道这个方法返回了什么类型的对象(没有多态,所以你不能返回基类类型的对象):
A a = (A)getObject(1)
B b = (B)getObject(2)
BTW最好使用Enum来定义对象类型,而不是int。
因此,当客户端知道将返回什么方法时,为什么不为客户端创建两个单独的方法?
A a = getA()
B b = getB()
如果这些对象具有相同的目的,最好在这里使用继承形式基类:
C c = getObject(ObjectType.A);
答案 6 :(得分:0)
我会将Adeel的答案与Dictionary结合使用来存储类型与int的组合。由于您使用整数来识别类型,因此无论如何都需要在它们之间进行映射。
Dictionary<int, Type> dictionary = new Dictionary<int, Type>();
//fill the Dictionary with all int/Type-combinations
{
int objectType;
Type type = dictionary[objectType];
var genericMethodInfo = this.GetType().GetMethod("GetObject").MakeGenericMethod(type);
object newObject = genericMethodInfo.Invoke(this, null);
var objectInCorrectType = Convert.ChangeType(newObject, type);
}
public T GetObject<T>() where T : new()
{
return new T();
}
答案 7 :(得分:0)
你真的必须使用if语句。我可能会这样做:
var result = getObject(...);
if (result is A) { ... }
else if (result is B) { ... }
但是,你有一个非常奇怪的方法叫做getObejct()。因为,你必须传递一个int来获得结果类型;这意味着您已经知道所需的对象类型。所以,当你想要A做“var a =(A)getObject(1)”时,你想要B做“var b =(b)getObject(2)”。