Сообщите компилятору, что неявное преобразование существует для типа generi c - PullRequest
0 голосов
/ 16 января 2020

Рассмотрим следующий код:

class SomeType1
{
}

class SomeType2
{
}

class CombinedType
{
    public static implicit operator CombinedType(SomeType1 source)
    {
        return new CombinedType
        {
            ...
        };
    }

    public static implicit operator CombinedType(SomeType2 source)
    {
        return new CombinedType
        {
            ...
        };
    }
}

void SomeMethod()
{
    var listOfType1 = new List<SomeType1>();
    DoSomethingWith(listOfType1);

    var listOfType2 = new List<SomeType2>();
    DoSomethingWith(listOfType2);
}

void DoSomethingWith<T>(IEnumerable<T> stuff)
{
    IEnumerable<CombinedType> converted = stuff.Select(i => (CombinedType) i);
    ...
}

Сбой при

Ошибка CS0030 Невозможно преобразовать тип 'T' в 'CombinedType'

Однако я знаю, что существует неявное преобразование между T и CombinedType, когда T равно SomeType1 или SomeType2. Как я могу сказать компилятору, что это должно быть возможно? Я не могу добавить where T : CombinedType в метод generi c, потому что это не так.

Ответы [ 2 ]

2 голосов
/ 16 января 2020

Неявные преобразования - это просто вызовы методов, которые вставляются компилятором во время компиляции.

Например:

CombinedType c = new SomeType1();

превращается в:

CombinedType c = CombinedType.op_Implicit(new SomeType1());

JIT не обладает знаниями для вставки этих вызовов методов. Тем не менее, дженерики расширяются во время JIT, когда вы хотите, чтобы это произошло.

Не забывайте, что ваш код также позволяет кому-то передавать T, который не конвертируется в CombinedType.


Однако у вас есть несколько вариантов.

Один из них:

void DoSomethingWith<T>(IEnumerable<T> stuff)
{
    IEnumerable<CombinedType> converted = stuff.Select(i => i switch
    {
        SomeType1 s1 => (CombinedType)s1,
        SomeType2 s2 => (CombinedType)s2,
        _ => throw ...
    });
}

Другой - что-то вроде:

public interface IConvertibleToCombinedType
{
    CombinedType ConvertToCombinedType();
}

public class SomeType1 : IConvertibleToCombinedType
{
    // ... or get rid of the implicit conversion, and put the logic here
    public CombinedType ConvertToCombinedType() => this;
}

public class SomeType2 : IConvertibleToCombinedType
{
   ...
}

void DoSomethingWith<T>(IEnumerable<T> stuff) where T : IConvertibleToCombinedType
{
    IEnumerable<CombinedType> converted = stuff.Select(i => ConvertToCombinedType());
    ...
}
0 голосов
/ 16 января 2020

Вы можете создать общий фиктивный интерфейс, например interface ICombinedType {}, заставить его реализовать все 3 класса, а затем добавить where T : ICombinedType в метод generi c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...