2014-01-14 3 views
5

Я создал метод IEnumerable, который принимает IEnumerable типа PERSON, который меняет местами имена и фамилии сотрудника (они в настоящее время добавляют их в базу данных в одном поле («Джон Смит», «Крэйг Робертсон») и т.д.Создание метода типа IEnumerable, который принимает общий тип

у меня есть еще один IEnumerable называется ProjectPerson, который имеет сходные, но иные данные, которые я хотел бы поменять имя и фамилию как хорошо.

Оба 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 to IPerson), а также« Наилучшее соответствие метода перегрузки для SwapFirstAndLastNames (IEnumerable) имеет некоторые недопустимые аргументы.

Оба человека и projectPerson имеют тип IENumerable (как и подчеркнутые), а используемые в каждом из них данные используются в других местах для заполнения датагрид и т. П. Поэтому я в основном ищу один метод, который принимает любой тип IEnumerable, меняет область IEnumerable.Name (у меня уже есть код, чтобы сделать это), а затем возвращает измененные данные IEnumerable. У меня есть работа над одним типом.

ответ

1

экстракт супер класс или сделать интерфейс, то вы можете сделать:

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

Вам нужно использовать следующий синтаксис для определения метода.

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;} 
} 
+0

Вы были первым с этим ответом, мне интересно, почему это не поддерживается –

+1

+1, но, как вы уже упоминали, дженерики вообще не нужны. –

+0

@TimSchmelter Я согласен, увидев ваш ответ, общий соответствует оригинальному шаблону OP, но нет необходимости в нем, если вы используете интерфейс. Однако я не хотел редактировать мои, чтобы соответствовать вашим, или мы просто закончим с дублирующимися ответами! – Liath

5

Может быть soultion является извлечь интерфейс?

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

+1 для того, чтобы придумать то же самое решение, что и я (это, безусловно, лучший ;-)) – Liath

+0

Спасибо, Дмитрий, я попробую! – iandavidson1982

+1

Странно .. Я бы подумал, что абстрактное Лицо было бы подходящим решением здесь. –

5

Я хотел бы создать интерфейс, который содержит все необходимые свойства, как

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<INamedEntity> для обмена FirstName и Lastname, которые вы можете использовать для Persons и ProjectPersons:

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

Согласен, общий здесь не требуется –

+1

Мне нравится этот ответ - я не считаю, что общие файлы необходимы, если вы используете интерфейс. – Liath

+0

Когда я пытаюсь использовать этот метод: _projectPerson = SwapFirstAndLastNames (projectPersons) я получаю сообщение об ошибке, как он пытается преобразовать тип IEnumerable к интерфейсу (IPerson/INamedEntity) Моего метода возвращающей IEnumerable -> public static IEnumerable SwapFirstAndLastNames (IEnumerable человек) – iandavidson1982

Смежные вопросы