泛型还是只使用重载?
Posted
技术标签:
【中文标题】泛型还是只使用重载?【英文标题】:Generics or just use overloads? 【发布时间】:2012-01-05 14:57:50 【问题描述】:我有 3 个类,都具有相似的属性。在所有 3 个类中,其中 3 个属性的名称完全相同。与其编写 3 个方法(每个类一个),有什么方法可以在这里利用泛型吗?
public static String GetAString(ActivityMedia activityMedia)
return activityMedia.name;
public static String GetAString(AuditMedia auditMedia)
return auditMedia.name;
public static String GetAString(VehicleMedia vehicleMedia)
return vehicleMedia.name;
编辑:显然是为了简单地将这 3 种类类型之一的对象传递给 GetAString()
【问题讨论】:
这些类是否共享一个接口? 是否可以选择为这些类提供一个通用的Media
超类或接口?
他们不共享一个接口号。它们只是完全独立的类。
【参考方案1】:
-
使用单个
string Name
属性引入接口
按接口标记所有三个类
现在您可以直接评估媒体名称我不知道为什么您需要一个方法,但无论如何,您可以为接口类型创建扩展方法IMedia
interface IMedia
string Name get;
class ActivityMedia : IMedia
class AuditMedia : IMedia
class VehicleMedia : IMedia
static class MediaExtensions
public static string GetName(this IMedia instance)
return instance.Name;
【讨论】:
如果您使用接口,您不认为在所有 ActivityMedia、AuditMedia、VehicleMedia 类上实现 Name 属性是多余的吗?虽然界面有不同的用途 你不需要实现它,因为这三个媒体都已经有了 Name 属性,这就是我们说的标记接口 它的副本,不是吗?你说什么?【参考方案2】:另一种选择是使用接口...
public interface INameable
String Name get;
public static String GetAString(INameable nameable)
return nameable.Name;
虽然此时您可能甚至不需要 GetAString 方法?
【讨论】:
【参考方案3】:你可以通过界面来做到这一点
public interface INamedMedia
string Name get;
那么你的方法就变成了
public static String GetAString(INamedMedia media)
return media.Name;
你的类实现INamedMedia
public class Media : INamedMedia
public string Name get return "Media";
【讨论】:
【参考方案4】:我原以为界面会是这里的理想解决方案:
public interface IMedia
public String Name get;
然后你可以让你的静态方法将该接口类型作为它的参数:
public static String GetAString(IMedia media)
return media.Name;
或者您的所有媒体类都可以派生自包含您需要的属性的基类型,并将其传递给方法而不是接口。
很难告诉您哪个是更好的选择,因为这取决于您的应用程序的复杂性和继承链。
这个article可能会有所帮助
【讨论】:
【参考方案5】:如果它们完全不相关,一种选择是使用dynamic
(如果您使用的是 C# 4):
public static String GetAString(dynamic d)
return d.name;
编辑:
如果你没有使用 C# 4.0,你可以使用反射:
public static string GetAString(object o)
System.Reflection.PropertyInfo name = o.GetType().GetProperty("name");
return (string) name.GetValue(o, null);
【讨论】:
不幸的是,我们还没有达到 4。如果我们是的话,那看起来像是完美的解决方案。我会调查一下。 哪里提到了 .NET 4? 或者,您可以使用反射。 我不明白这个讨论的去向!?如果我在 C# 4 中编码,Vlad 已经提出了一个解决方案,仅此而已。 @ChrisBD : 很明显你来这里是一个 bti 之后所以没有指定if .NET 4...
就无法看到原始答案【参考方案6】:
您不需要泛型,您需要 OOP 和继承。
将ActivityMedia
、AuditMedia
和VehicleMedia
全部设为实现IMedia
之类的基本接口或派生MediaBase
之类的基本类
然后您只编写一次方法GetAString
,它接受IMedia
对象或MediaBase
对象。
另一种选择可能是您在ActivityMedia
、AuditMedia
和VehicleMedia
中覆盖默认的ToString
方法,以便只返回名称属性,然后您只需调用ToString
而无需任何@987654334 @方法。
【讨论】:
【参考方案7】:如果这些类没有共同的祖先,泛型将无法帮助您。解决方案是通过声明具有name
属性的接口来安排它们共享共同祖先。让每个类都实现该接口,然后您就可以拥有一个GetAString
函数。
【讨论】:
【参考方案8】:如果这三个类具有相同属性的子集,则最好实现一个基类,而不是在派生三个媒体类的基类中声明的公共属性和方法。
public class ActivityMedia : Media
public class Media
public string Name get;set;
这样三个类在一个地方定义了一组方法,使得代码更容易维护。同时让您可以灵活地将特定于类的方法放入其派生实现中。
【讨论】:
【参考方案9】:这里实现继承比泛型更符合逻辑。
您也可以使用Interface
,但这会使您的Name
属性在您的所有ActivityMedia
、AuditMedia
、VehicleMedia
类上重复。
考虑一个基类Media
public class Media
// consider all properties that are common
// on Media domain
public string Name get; set
并从Media
类继承ActivityMedia
、AuditMedia
、VehicleMedia
。
public class ActivityMedia : Media
// other properties on ActivityMedia domain
public class AuditMedia : Media
// other properties on AuditMedia domain
public class VehicleMedia : Media
// other properties on VehicleMedia domain
现在在您的 GetAString
方法上使用 Media
类
public static String GetAString(Media activityMedia)
return activityMedia.name;
public static String GetAString(Media auditMedia)
return auditMedia.name;
public static String GetAString(Media vehicleMedia)
return vehicleMedia.name;
【讨论】:
继承有时是个魔鬼,当你想在三个类之间共享单个属性时,通过基类(而且不是抽象的)来实现是个坏主意【参考方案10】:这就是继承来拯救你的地方。有这样的基类:
public class Media
public string name get return "Media";
那么每个类都会继承并定义自己的名字:
public class ActivityMedia : Media
public new string name get return "Activity Media";
最后:
public static String GetAString(Media media)
return media.name;
编辑:当您坚持当前的设计时,您可以使用反射:
public static String GetAString(object media)
PropertyInfo propName = media.GetType().GetProperty("name");
if (propName != null)
return propName.GetValue(media, null);
return "";
【讨论】:
我不会决定重新设计这些类以从媒体类继承。我现在几乎坚持使用单独的类。我明白你的意思,我把它作为答案的其他地方。 查看我的编辑,无论对象类型是什么,它都会查找名为“name”的属性并获取其值。以上是关于泛型还是只使用重载?的主要内容,如果未能解决你的问题,请参考以下文章