Цепные неявные операторы в общих классах c # - PullRequest
6 голосов
/ 14 мая 2011

Для следующего общего класса c # я хотел бы преобразовать T в K:

public abstract class ValueType<T,K> : IValueType<T> where K : ValueType<T,K>,new()
{     
    public abstract T Value { get; set; }     

    public static implicit operator ValueType<T,K>(T val) 
    {         
        K k = new K();
        k.Value = val;
        return k;    
    }
}

Если бы я реализовал прямой оператор implicit operator K(T val), это привело бы к ошибке времени компиляции (CS0556).

Я подумал, что могу попробовать связать неявные операторы:

public static implicit operator K(ValueType<T,K> vt){
    return (K)val;
}

, но следующий пример все еще жалуется на невозможность его преобразования:

public class Test : ValueType<int, Test>
{
    public override int Value{ get; set; }
}

Test t = 6; //complains it's unable to be converted
Console.WriteLine(t.Value);

Я действительно хочу избегать явного приведения, если это возможно.

Этот вопрос распространяется на еще один вопрос SO , который я поднимал ранее.

Ответы [ 3 ]

13 голосов
/ 14 мая 2011

Правила для реализации вашей собственной логики неявного преобразования довольно строги, и вам, вероятно, следует хорошо ознакомиться с разделами 6.4.4 и 10.10.3 спецификации, если вы собираетесь делать особенно сложные, подобные этой.

Вкратце, следует знать несколько ключевых правил:

  • Тип, в котором вы определяете преобразование, должен отображаться в части «к» или «от» пользовательского преобразования. Вы не можете создать класс C, который определяет преобразование из E в F; С должен быть где-то там.
  • Невозможно заменить встроенное неявное преобразование на ваше собственное; например, при конвертировании из C в объект нельзя выполнить особые действия.
  • Определяемые пользователем неявные преобразования будут «сцеплены» с двумя встроенными неявными преобразованиями, но не с любыми другими пользовательскими преобразованиями. Например, если у вас есть неявное пользовательское преобразование из C в D и встроенное неявное преобразование из D в IFoo, вы получаете неявное преобразование из C в IFoo. Но если D имеет пользовательское неявное преобразование в E, то вы не получите неявное преобразование из C в E бесплатно.
2 голосов
/ 14 мая 2011

Приведения не объединяются компилятором, поэтому способ решения проблемы не работает.

Неявные приведения довольно строги в проверке типов. Ваш самый первый фрагмент и Test класс do работают, если компилятор знает тип:

ValueType<int, Test> t = 6;
Console.WriteLine(t.Value);

Проблема в том, что ваш ValueType<int, Test> - с точки зрения системы типов - не всегда Test, поэтому неявное преобразование там не применяется.

Эрик Липперт написал сообщение в блоге , кстати, об этом типе самореференции - стоит прочитать!

0 голосов
/ 14 мая 2011

Насколько я знаю, я не думаю, что вы можете соединять цепочки между собой, извините за это.

Я изучал, как создавать парсеры, и если бы это было возможно, было быбыть неопределенным циклом, чтобы найти соединение от T до K.Я не уверен, что парсер C # попытался бы сделать это, но мои деньги на нет, к сожалению!

...