Возможно ли в С# перегрузить общий оператор трансляции следующим образом?
Просто интересно, есть ли в любом случае представить следующий код в С# 3.5:
public struct Foo<T> {
public Foo(T item) {
this.Item = item;
}
public T Item { get; set; }
public static explicit operator Foo<U> ( Foo<T> a )
where U : T {
return new Foo<U>((U)a.Item)
}
}
Спасибо
Ответы
Ответ 1
Операторы преобразования не могут быть общими. Из раздела спецификации 10.10 здесь представлен формат конвертера-оператора-декларатора:
conversion-operator-declarator:
implicit operator type ( type identifier )
explicit operator type ( type identifier )
Сравните это с, скажем, с заголовком метода:
<я > метод заголовка: attributes opt методы-модификаторы opt partial opt <я > возвратного типа имя-члена type-parameter-list opt (format-parameter-list opt) тип-параметр-ограничители-положения <суб > неавтоматическогосуб >
(Извините за форматирование - не знаю, как это сделать лучше.)
Обратите внимание, что формат оператора не включает в себя список параметров типа или ограничения параметров типа.
Ответ 2
Ваш код сводится к строке: return new Foo<U>((U)a.Item)
Где вы пытаетесь присвоить базовый класс унаследованному классу, что невозможно.
Предположим, что T (базовый класс) имеет тип Stream
, а U имеет тип MemoryStream
(унаследованный класс), вы не можете назначить Stream
переменной типа MemoryStream
.
Ответ 3
Я думаю, что короткий ответ: "Невозможно. Попробуйте вместо этого использовать метод"
Также кажется, что это обман этого вопроса
Решение для перегруженного ограничения оператора в .NET файлах
Ответ 4
Похоже, вы хотите контравариантное преобразование, но struct
неизменяемы, конверсия ничего не покупает, вы можете просто сказать new Foo<U>((U)a.Item)
, как указал @Gidon.
Если вы решили изменить Foo
как класс, то мы можем сделать некоторые изменения:
public interface IFoo<in T> {
T Item {
set;
}
}
public class Foo<T>:IFoo<T> {
public Foo(T item) {
this.Item=item;
}
public T Item {
get; set;
}
// public static explicit operator Foo<U>(U a) {
// return new Foo<U>((U)a.Item);
// }
}
и используйте его как:
var foo = new Foo<object>(new object { });
IFoo<String> bar = foo;
bar.Item="123";
var b = Object.ReferenceEquals(foo, bar); // true
Кстати, дисперсия в общих интерфейсах доступна только из .netfx 4.0.