我知道这可能是一个非常简单的问题,但我目前正在做脑屁。我正在尝试创建一个可以采用2种自定义类型之一的方法。基本上这个方法的主体对于两种类型都是相同的,因为它们都具有Name属性(我在Name属性上进行比较以用于排序)。我该怎么做?
我的第一个想法是用两种类型作为参数重载方法:
int Compare(Type1 first, Type1 second)
int Compare (Type2 first, Type2 second)
但这些方法的主体最终是相同的,因此它似乎是一种浪费。
我的下一个想法是使用泛型,但这似乎并不正确,因为我并没有真正使它成为通用的,因为它只能用于2种特定类型。
澄清:“自定义”类型实际上不是我的自定义类型。我的意思是他们不是内置类型。我无法控制这些类型或继承层次结构中的内容。他们碰巧都有Name属性。
答案 0 :(得分:8)
奇怪的是到目前为止还没有人发布我认为是明显的选择:将名称作为比较的参数。使调用者从对象中获取name属性。如果需要使用的所有方法都是名称,那么为什么要传递对象的其余部分呢?
如果你需要抽象出“我可以从这个东西中得到一个名字”的概念,那么就这样做:
示例:
int Compare(string name1, string name2) { ... whatever ... }
int Compare<T>(T t1, T t2, Func<T, string> getName)
{
return Compare(getName(t1), getName(t2));
}
现在你可以说:
Compare(car1, car2, c=>c.Name);
Compare(employee1, employee2, e=>e.Name);
等等。
答案 1 :(得分:7)
如果两种类型派生自相同的基础或使用相同的接口,并且没有其他类使用基础和/或接口,则通用仍然是一种选择。
int Compare<T>(T first, T second) where T : IHasName
除此之外,有两个重载是要走的路。
注意:如果你有.NET 4,你可以使它成为运行时事物并使方法动态化。
int Compare(dynamic first, dynamic second)
在这种情况下,你抛出的任何内容都会编译,但如果Name
属性不存在,它会在运行时爆炸。
就个人而言,如果我无法修改类型以使用通用接口,那么我会使用重载并获得编译时的安全性。
答案 2 :(得分:4)
好的,我在第一个答案中完全看错了你的问题。这是一个更好的一个:)
超载是你最好的选择。由于比较结果仅取决于Name
,因此请创建一个 比较的方法,然后调用它:
private int Compare(string first, string second)
{
// do comparison
}
public int Compare(Type1 first, Type1 second)
{
return Compare(first.Name, second.Name):
}
public int Compare(Type2 first, Type2 second)
{
return Compare(first.Name, second.Name);
}
编辑:
由于你有多个项目,你可以做两件事:
public int Compare(string first1, string second1, X first2, X second2 ...
但这会变得有点难看。另一种方法是提供一个提取值的投影:
private int Compare<T>(T first, T second, Func<T,Tuple<string,int,TypeX,TypeY>> projection)
{
// test for first==null, second==null, etc...
var nicerFirst = projection(first);
var nicerSecond = projection(second);
// compare objects using nicerFirst.Item1, nicerFirst.Item2, etc.
}
然后您的比较看起来像:
int Compare(Type1 first, Type1 second)
{
return Compare(first, second, x => Tuple.Create(x.Name, x.Int, x.X, x.Y));
}
答案 3 :(得分:1)
如果它只能 与2种类型一起使用,那么就会产生2次重载。
答案 4 :(得分:1)
重载方法是一种很好的方法,只需要两种特定的类型。为避免重复代码,您可以在场景后面使用泛型:
public int Compare(Type1 first, Type1 second) {
return Compare<Type1>(first, second);
}
public int Compare(Type2 first, Type2 second) {
return Compare<Type2>(first, second);
}
private int Compare<T>(T first, T second) {
...
}
答案 5 :(得分:0)
也许不是最好的解决方案,但这是我想到的: 你做了一个像这样的方法:
int MainCompare(Type1 first1, Type1 second1, Type2 first2, Type2 second2, bool firsttype){...}
然后你可以用两行比较方法。
int compare(Type1 first, Type1 second){
return MainCompare(first, second, null, null, true);
}
int compare(Type2 first, Type2 second){
return MainCompare(null, null, first, second, false);
}
你的MainCompare会根据它使用的类型改变一点。
答案 6 :(得分:0)
这可能是一个无法解决的问题,但您可以为这两个类创建适配器,并让它们实现一个通用接口:
public class MyType1 : ICommonInterface, Type1
{
// Where you can define 'Somethin' in the common interface
public string Something
{
get { return base.Something; }
set { base.Something = value; }
}
/* ... */
}
public class MyType2 : ICommonInterface, Type2
{
// If there is no base.Something on Type2, you can re-name it assuming
// its intent is the same as Something
public string Something
{
get { return base.SomethingElse; }
set { set base.SomethingElse = value; }
}
}
然后你可以基本上完全实现@Anthony Pegram(+1)所拥有的:
int Compare<T> (T first, T second) where T : ICommonInterface
{
return first.Something.CompareTo(second.Something);
}