Подтвердить что ты не робот

Возможно ли в С# перегрузить общий оператор трансляции следующим образом?

Просто интересно, есть ли в любом случае представить следующий код в С# 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)
    }
}

Спасибо

4b9b3361

Ответ 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.

Ответ 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.