【问题标题】:Creating a method of IEnumerable type that takes in generic type创建一个接受泛型类型的 IEnumerable 类型的方法
【发布时间】:2014-01-14 09:00:03
【问题描述】:

我创建了一个 IEnumerable 方法,该方法接受一个 PERSON 类型的 IEnumerable,它交换员工的名字和姓氏(他们目前正在将它们添加到单个字段中的数据库中(“John Smith”、“Craig Robertson” ) 等。

我有另一个名为 ProjectPerson 的 IEnumerable,它具有相似但不同的数据,我也想交换其名字和姓氏。

两个 IEnumerables 都有“名称”作为字段,因此代码对两者都适用,我只想能够重复使用此代码,而不会使用 IEnumerabe<Person> 和另一个使用 IEnumerable<ProjectPerson> 但相同的代码创建重载在每个里面。

有没有办法设置不同类型可以使用的 IEnumerable 方法?也许将类型作为参数传递然后强制转换?

我创建了一个名为 IPerson 的接口:

    public interface IPerson
    {
        string Name { get; set;}
    }

我有以下几点:

public class Person: IPerson {..}

public class ProjectPerson: IPerson {..}

我的方法如下所示:

private void IEnumerable<IPerson> SwapFirstAndLastNames(IEnumerable<IPerson> persons)
{
    foreach (var employee in persons)
    {
        //do the swapping
    }
    return persons;
}

我在类的其他地方使用这两行调用这个方法:

_projectPerson = SwapFirstAndLastNames(projectpersons) 

_person = SwapFirstAndLastNames(person);

使用上述方法,我在该方法上收到错误消息“无法从 ProjectPerson 转换为 IPerson(与 Person 到 IPerson 相同),并且“与 SwapFirstAndLastNames(IEnumerable) 匹配的最佳重载方法有一些无效参数。

person 和 projectPerson 都是 IENumerable 类型(下划线的也是),并且每个中使用的数据都用于其他地方来填充数据网格等。所以我基本上是在寻找一种采用任何类型的 IEnumerable 的方法,交换 IEnumerable.Name 字段(我已经有了执行此操作的代码),然后返回交换的 IEnumerable 数据。我在单一类型上工作。

【问题讨论】:

    标签: c# generics ienumerable


    【解决方案1】:

    您需要使用以下语法来定义方法。

    private void IEnumerable<T> SwapFirstAndLastNames(IEnumerable<T> persons) where T : IPerson
    {
        foreach (var employee in persons)
        {
           //do the 
        }
        return persons;
    }
    

    注意where T : IPerson 这限制了您的方法,因此它只能由实现此接口的类调用(例如,您不希望有人传入整数!)。您将实现 ProjectPerson 和 Person 的此接口,并包括您的方法需要运行的所有字段(可能是名字/姓氏)。

    界面看起来像

    public interface IPerson
    {
      Firstname {get;set;}
      Lastname {get;set;}
    }
    

    【讨论】:

    • 你第一个回答这个问题,我想知道为什么它没有被投票
    • @TimSchmelter 看到您的回答后我同意,泛型与 OP 的原始模式匹配,但如果您使用该接口,则不需要它。但是我不想编辑我的来匹配你的,否则我们最终会得到重复的答案!
    【解决方案2】:

    我会创建一个包含所有相关属性的接口,例如

    public interface INamedEntity
    {
        string FirstName { get; set; }
        string LastName { get; set; }
    }
    

    你的两个类都应该实现它:

    public class Person : INamedEntity
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }         
    }
    
    public class ProjectPerson : INamedEntity
    {
        public string FirstName { get; set; }
        public string LastName { get; set; } 
    }
    

    现在您可以为IEnumerable&lt;INamedEntity&gt; 创建一个扩展方法来交换FirstNameLastname,您可以将其用于PersonsProjectPersons

    public static void SwapFirstAndLastNames(this IEnumerable<INamedEntity> persons)
    {
        foreach (var person in persons)
        {
            string oldLastName = person.LastName;
            person.LastName = person.FirstName;
            person.FirstName = oldLastName;
        }
    }
    

    【讨论】:

    • 同意,这里不需要通用
    • 我喜欢这个答案 - 如果您使用该接口,我认为不需要泛型。
    • 当我尝试使用此方法时:_projectPerson = SwapFirstAndLastNames(projectPersons) 我收到错误,因为它试图将类型 IEnumerable 转换为接口(IPerson / INamedEntity)我的方法正在返回一个 IEnumerable -- > 公共静态 IEnumerable SwapFirstAndLastNames(IEnumerable 人)
    • @iandavidson1982:这是一种扩展方法(它不需要是一个)。您可以在 IEnumerable&lt;INamedEntity&gt; 上调用它,就好像它存在于该类型上一样,或者只是作为静态方法。但是,它是void,所以它不会返回任何东西。您可能需要在问题中展示您尝试过的内容,因为在 cmets 中很难理解,其他人也可以提供帮助。
    • 嗨蒂姆。我创建了一个接口并更改了我的 Person 和 ProjectPerson 类以使用此接口。我正在使用 private IEnumerable SwapFirstAndLastNames(IEnumerable persons) {..} 我使用以下两行调用 -> _person = SwapFirstAndLastNames(person);和 _projectPerson = SwapFirstAndLastNames(projectpersons);
    【解决方案3】:

    可能是提取接口

      public interface IPerson {
        String FirstName {get; set}
        String LastName {get; set}
      }
    
      public class Person: IPerson {...}
    
      public class ProjectPerson: IPerson {...}
    
      private void IEnumerable<T> SwapFirstAndLastNames(IEnumerable<T> persons) 
        where T: IPerson
      {
        foreach (var employee in persons)
        {
            // You can operate with FirstName/LastName as you like here 
        }
        return persons;
      }
    

    【讨论】:

    • +1 提出了与我相同的解决方案(这显然是最好的 ;-))
    • 谢谢德米特里,我试试看!
    • 奇怪..我本以为抽象的 Person 会是合适的解决方案。
    • @Lews Therin:这取决于继承了哪些类 Person 和 ProjectPerson ;人们总是可以提取一个接口,这是一项容易的任务,相反,更改基类可能是一个非常复杂的问题。
    • @DmitryBychenko 也许……也许不是。但是使用接口给人的印象是 Person 可以被实例化。如果在这种情况下可以,那我猜也没关系。
    【解决方案4】:

    提取超类或制作接口,然后你可以这样做:

    private void IEnumerable<T> SwapFirstAndLastNames(IEnumerable<T> persons) where T : PersonSuperClass
    { 
    ... 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多