泛型还是只使用重载?

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 和继承。

ActivityMediaAuditMediaVehicleMedia 全部设为实现IMedia 之类的基本接口或派生MediaBase 之类的基本类

然后您只编写一次方法GetAString,它接受IMedia 对象或MediaBase 对象。

另一种选择可能是您在ActivityMediaAuditMediaVehicleMedia 中覆盖默认的ToString 方法,以便只返回名称属性,然后您只需调用ToString 而无需任何@987654334 @方法。

【讨论】:

【参考方案7】:

如果这些类没有共同的祖先,泛型将无法帮助您。解决方案是通过声明具有name 属性的接口来安排它们共享共同祖先。让每个类都实现该接口,然后您就可以拥有一个GetAString 函数。

【讨论】:

【参考方案8】:

如果这三个类具有相同属性的子集,则最好实现一个基类,而不是在派生三个媒体类的基类中声明的公共属性和方法。

public class ActivityMedia : Media 




public class Media

     public string Name get;set;

这样三个类在一个地方定义了一组方法,使得代码更容易维护。同时让您可以灵活地将特定于类的方法放入其派生实现中。

【讨论】:

【参考方案9】:

这里实现继承比泛型更符合逻辑。

您也可以使用Interface,但这会使您的Name 属性在您的所有ActivityMediaAuditMediaVehicleMedia 类上重复。

考虑一个基类Media

public class Media

    // consider all properties that are common
    // on Media domain
    public string Name  get; set 

并从Media类继承ActivityMediaAuditMediaVehicleMedia

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”的属性并获取其值。

以上是关于泛型还是只使用重载?的主要内容,如果未能解决你的问题,请参考以下文章

您可以使用泛型进行方法重载并且只更改方法签名的泛型类型吗?

React Typescript 泛型类型重载(例如 useState)

使用不在参数中的第一个泛型类型重载泛型函数

泛型函数的重载可以对其他重载开放吗?

打字稿、泛型和重载

无法用类型约束重载泛型方法[重复]