【问题标题】:How to create a generic method overload in C#?如何在 C# 中创建泛型方法重载?
【发布时间】:2016-09-14 20:28:53
【问题描述】:

我有 3 个函数,它们是相同类型的分支。

public interface k
{
    void CreateOrUpdate(IList<TagInfoForRecommender> tagList, IndexType indexType);
    void CreateOrUpdate(IList<ArtifactInfoForRecommender> artifactList, IndexType indexType);
    void CreateOrUpdate(IList<UserInfoForRecommender> userList, IndexType indexType);
}

我想创建一种泛型类型,其中继承接口的实现类可以编写函数的重载方法。

我试过了

public interface k
{    
    void CreateOrUpdate<T>(IList<T> tagList, IndexType indexType) 
        where T : BaseInfoForRecommender;
}

但它只能在实现的类中创建一个方法。

我想在

中创建重载
public class d : K
{
    CreateOrUpdate<TagInfoForRecommender>(IList<TagInfoForRecommender> tagList, IndexType indexType)
    {
        //impelement sth
    }

    CreateOrUpdate<TagInfoForRecommender>(IList<TagInfoForRecommender> tagList, IndexType indexType)
    {
        //impelement sth
    } 
}

【问题讨论】:

  • 目前尚不清楚重载会出现在哪里。您能否给出一个完整(但最少)的示例来说明您希望能够做什么?
  • 请写一些代码(你想要的变种,即使它没有编译)。
  • 我已经编辑了帖子。我想要实现接口中的重载
  • 这不是泛型的用途。无论T如何,他们都应该提供一个相同的模板。否则,您将不得不在方法内部的typeof(T) 上进行分支,这几乎不会使设计变得更好。这是某种存储库模式吗?因为 EF/NHibernate 通常具有不关心确切类型的通用创建/更新方法。

标签: c# generics overloading


【解决方案1】:

你可以使用通用接口

public interface K<T> where T : BaseInfoForRecommender{
  void CreateOrUpdate(IList<T> list, IndexType indexType); 
}

然后为每种类型多次实现接口

public class d : K<TagInfoForRecommender>,
                 K<ArtifactInfoForRecommender>, 
                 K<UserInfoForRecommender> {
  public void CreateOrUpdate(IList<TagInfoForRecommender> list, IndexType indexType) {...}
  public void CreateOrUpdate(IList<ArtifactInfoForRecommender> list, IndexType indexType) {...}
  public void CreateOrUpdate(IList<UserInfoForRecommender> list, IndexType indexType) {...}
}

【讨论】:

  • 我唯一关心的是您的答案(我觉得这很好),只有当您只有返回类型时才会更改签名。您必须(显式实现您的方法并)将您的实例投射到特定接口上,否则您将无法访问您的方法。即使它允许像我的回答那样避免异常和类型检查。总是将实例强制转换为访问每个方法可能很烦人。纠正我,如果我错了。
  • @romain-aga 不,你是对的。有时它可能很麻烦,但这取决于应用程序的其余部分以及它如何使用代码。但是在这种情况下,方法签名总是不同的,你不需要显式地实现它。
  • 您始终可以添加一个通用的 CreateOrUpdate 来调用特定的 CreateOrUpdate public void CreateOrUpdate&lt;T&gt;(IList&lt;T&gt; list, IndexType indexType) where T : BaseInfoForRecommender { ((K&lt;T&gt;)this).CreateOrUpdate(list, indexType); } 如果您使用未实现的类型调用该方法,则确实存在导致运行时错误的风险。
  • 在实现的类中只能创建一个或我想要的任意多个,对吗?
  • 这是最接近我想要的,但我认为我不应该这样做。
【解决方案2】:

你不能这样做。

唯一可以接近你想要达到的目标(如果我很好地理解你的问题的话)是做一些类型检查:

public interface IAbstraction
{
    void CreateOrUpdate<T>(IList<T> tagList, IndexType indexType)
        where T : BaseInfoForRecommender;
}

实施:

public class Concrete : IAbstraction
{
    void CreateOrUpdate<T>(IList<T> tagList, IndexType indexType)
        where T : BaseInfoForRecommender
    {
         var dict = new Dictionary<Type, Action<IList<object>, IndexType>()
         {
             { typeof(TagInfoForRecommender),
                 (tagList, indexType) => CreateOrUpdateTagInfoForRecommender(list.Cast<TagInfoForRecommender>(), index) },

             { typeof(ArtifactInfoForRecommender),
                 (tagList, indexType) => CreateOrUpdateArtifactInfoForRecommender(list.Cast<ArtifactInfoForRecommender>(), index) },

             { typeof(UserInfoForRecommender),
                 (tagList, indexType) => CreateOrUpdateUserInfoForRecommender(list.Cast<UserInfoForRecommender>(), index) },
         };
         dict[typeof(T)](tagList.Cast<object>(), indexType);
    }

    private CreateOrUpdateTagInfoForRecommender(IList<TagInfoForRecommender> tagList, IndexType indexType)
    {
    }

    private CreateOrUpdateArtifactInfoForRecommender(IList<ArtifactInfoForRecommender> tagList, IndexType indexType)
    {
    }

    private CreateOrUpdateUserInfoForRecommender(IList<UserInfoForRecommender> tagList, IndexType indexType)
    {
    }
}

我想你可以写一些更好的东西,因为我没有尝试我的代码(你应该有一些错误)。但你有主要的想法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-09
    • 1970-01-01
    • 1970-01-01
    • 2021-02-18
    • 1970-01-01
    相关资源
    最近更新 更多