【问题标题】:Generic extension method for various types having the same properties具有相同属性的各种类型的通用扩展方法
【发布时间】:2016-08-30 06:23:21
【问题描述】:

我想知道,如果它们具有相同的属性,是否可以创建一个适用于一组不同类型的扩展方法? 例如:

public static T GetObjectByIdOrName<T>(this IEnumerable<T> collection, Mapping mapping) where T : IType1, IType2, IType3
    {
        return collection.FirstOrDefault(x => x.Id == mapping.ObjectId || x.Name == mapping.ObjectName);
    }

所有类型都有 Id 和 Name 属性,所以我希望这是可能的 - 但是,编译器告诉我 Type1.Id 和 Type2 Id 之间存在不明确的引用...

有什么方法可以实现吗? (我无法为他们创建一个共同的基础)

【问题讨论】:

  • 这些课程在你的控制之下吗?
  • 该约束意味着该类型必须实现所有 3 个接口。如果它们都公开相同的属性,那么在显式实现任何属性的情况下,它不知道应该通过哪个接口。
  • 你能重构让每个接口使用一个基本接口吗?
  • @Bartosz 在这种情况下,您能做的最好的事情就是为每个接口创建 3 个重载。那或使用动态。
  • @Bartosz - 我的回答中实际上包含了“动态”的使用。

标签: c# generics


【解决方案1】:

如果代码设计得当,这相当容易。只需让它们共享一个通用界面即可。

public interface IBase
{
    object Id{ get; set; }
    string Name{ get; set; }
}

public interface IType1 : IBase{}
public interface IType2 : IBase{}

public static T GetObjectByIdOrName<T>(this IEnumerable<T> collection, Mapping mapping) where T : IBase
{
    //... get T.Id or T.Name
}

否则,由于设计中没有隐式共享实现,您可以笨拙地假设属性将使用动态存在。

public static object GetObjectByIdOrName(this IEnumerable collection, Mapping mapping)
{
    return collection.Cast<dynamic>().FirstOrDefault(x => x.Id == mapping.ObjectId || x.Name == mapping.ObjectName);
}

【讨论】:

  • IType1IType2 来自外部项目
  • @Bartosz 请注意,动态会打开你的运行时类型错误,如果没有它们,这些错误会在编译时被捕获。使用它们时,性能也会受到一些影响。
  • 此外,动态方法仍然可以使用 Linq return collection.Cast&lt;dynamic&gt;().FirstOrDefault(x =&gt; x.Id == mapping.ObjectId || x.Name == mapping.ObjectName); 因为它不会编译,因为并非所有路径都返回。 (最后需要一个return null;)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-11
  • 2011-05-17
  • 1970-01-01
  • 1970-01-01
  • 2021-06-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多