Определение типа generi c в базовом классе - PullRequest
0 голосов
/ 07 августа 2020

У меня следующие классы. AuthorTest и BookTest оба наследуются от MyBaseClass, у которого есть метод AddName, который принимает общий c параметр.

public class Book {
    public string Name {get;set;}
}

public class Author {
    public string FirstName {get;set;}
    public string LastName {get;set;}
}

public class BookTest : MyBaseClass {
    Book book = // book object

    base.AddName<Book>(book);
}

public class AuthorTest : MyBaseClass {
    Author author = // author object

    base.AddName<Author>(author);
}

public interface IMyBaseClass {
    void AddName<T>(T item);
}

public class MyBaseClass : IMyBaseClass {
    public void AddName<T>(T item) {
        // item could either be Book or Name
        var name = item.Name

        // or

        var name = item.FirstName + " " item.LastName;
    }
}

В базовом классе, как определить, какой тип T (Книга или Автор) передается? И исходя из этого мне нужно построить переменную name. Есть ли элегантный способ сделать это?

Ответы [ 2 ]

0 голосов
/ 25 августа 2020

Мне кажется, вам лучше переместить параметр типа generi c из метода в сам тип. Вы пишете BookTest, а тест связан с Book, тогда более естественно определить ваш тип следующим образом: class BookTest : MyBaseClass<Book>.

Итак, вот базовые классы:

public interface IMyBaseClass<T>
{
    void AddName(T item);
}

public abstract class MyBaseClass<T> : IMyBaseClass<T>
{
    protected abstract string GetName(T item);
    
    public void AddName(T item)
    {
        var name = this.GetName(item);
    }
}

Затем вы пишете свои тесты следующим образом:

public class BookTest : MyBaseClass<Book>
{
    protected override string GetName(Book item)
    {
        return item.Name;
    }
}

public class AuthorTest : MyBaseClass<Author>
{
    protected override string GetName(Author item)
    {
        return $"{item.FirstName} {item.LastName}";
    }
}

Все они строго типизированы, и каждый класс несет четкую ответственность.

0 голосов
/ 07 августа 2020

Хотя и ваша иерархия, и использование универсальных шаблонов кажутся весьма сомнительными, простой ответ на ваш вопрос заключается в том, что вы выполняете проверку типа во время выполнения так же, как вы бы выполняли для типизированного параметра, как и для другого значения

public class MyBaseClass : IMyBaseClass
{
    public void AddName<T>(T item)
    {
        // item could either be Book or Author
        var name = item switch
        {
            Author a => $"{a.FirstName} {a.LastName}",
            Book b => b.Name,
            _ => throw new ArgumentException(nameof(item), $"Invalid type: {a?.GetType()}")
        };
    }
}

Однако, как уже указывали другие, поскольку вы поддерживаете только фиксированный набор типов, перегрузки были бы более подходящими.

public class MyBaseClass : IMyBaseClass
{
    public void AddName(Author author)
    {
        var name = $"{author.FirstName} {author.LastName}";
    }
    public void AddName(Book book) {
        var name = book.Name;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...