2017-01-05 2 views
4

У меня есть словарь, где оба ключа и значения имеют тип Type, как так ...Можете ли вы ограничить тип типа в родовом?

private static Dictionary<Type, Type> myDict; 

То, что я пытаюсь сделать, это ограничить второй Type для только быть типов, которые наследуют от FrameworkElement.

Примечание Я не storying FrameworkElement экземпляров, я пытаюсь хранить только объекты типа Type, которые вытекают из FrameworkElement делает следующее утверждение верно ...

var isTypeStorable = typeof(FrameworkElement).IsAssignableFrom(FooType); 

Так это может быть сделано?

BTW, да, я знаю, что я могу использовать приведенное выше, чтобы выполнить проверку выполнения перед добавлением в словарь (это то, что я сейчас делаю). Мне интересно, есть ли какие-либо функции на языке, которые позволили бы мне ограничить это во время компиляции.

+0

AFAIK нет нет. Вы можете создать специализированный словарь, переопределить методы «Добавить» и «ДобавитьRange» и выбросить, если вы получите плохой ввод, но это все равно обеспечит проверку ошибок во время выполнения. Я почти задаюсь вопросом, есть ли лучший способ сделать свою конечную цель, возможно, используя фабрику или какой-то ДИ? Можете ли вы немного рассказать о том, как используется словарь? –

+0

Это именно то, что я сейчас делаю. Это было более просто интересно о концепции/возможности в целом как о признаке языка. – MarqueIV

+0

Общее ограничение не помогает? что-то вроде «T: FrameworkElement» –

ответ

4

No, это невозможно. FrameworkElement.GetType() и FooType не имеют отношения к типу системы, оба только Type s. Если вы хотите ограничить общий набор, вам придется делать это с проверками времени выполнения и исключениями, общие ограничения вам не помогут.

Если вы знаете, что вы хотите хранить во время компиляции (или довольны какой-то сложной рефлексии) вы можете изменить свой API, чтобы не принимать Type, но использовать родовое вместо:

public void AddTypeForType(Type x, Type y) 

может быть заменен по

public void AddTypeForType<T1, T2>() where T1 : FrameworkElement 
{ 
    myDict.Add(typeof(T1), typeof(T2)); 
} 

Вы могли бы затем вызвать его так:

AddTypeForType<FrameworkDerivedClass, MyCustomClass>(); 

Но это скорее изменение API, чем ответ на ваш вопрос.

+0

Не уверен, что вы подразумеваете под своим вторым примером. Вы указали два общих типа, которые вы не используете в подписи. Даже не уверен, что это скомпилируется.Кроме того, T1 ограничивается экземпляром FrameworkElement * *, а не типом. Я пытаюсь ограничить его объектом типа, который либо есть, либо получен из типа FrameworkElement. – MarqueIV

+0

@MarqueIV Добавлен пример его вызова. Как я уже сказал, это изменение в API, которое приближается к тому, что вы хотите, но за счет сложного вызова, если вы не знаете фактические типы во время компиляции. – nvoigt

+0

Интересный подход! Но как вы могли бы назвать это во время выполнения с переменными типа Type? ... или вы бы просто использовали обычный метод Add с ручной проверкой в ​​этот момент? – MarqueIV

1

Я думаю, что нет ничего подобного, но вы можете добиться этого путем проверки пунктов, прежде чем добавить в словарь, я имел в виду что-то вроде этого:

Пусть Xx,Yy быть пункт, который я хотел бы добавить к myDict Так что я могу сделать, это, Первая проверка существования ключа, а затем для условия для значения (inherit from FrameworkElement.)

if(!myDict.ContainsKey(Xx) && /* Yy is inherited from FrameworkElement */) 
{ 
    myDict.Add(Xx,Yy); 
} 
+0

Да, это то, что я делал с моим флагом 'isTypeStorable'. Просто интересно, могу ли я получить это во время компиляции, а не во время выполнения. – MarqueIV

+1

@MarqueIV, если бы у меня был 'myDict.Add (CallExternalFunction(), CallExternalFunction()), как компилятор мог узнать возвращаемый тип' CallExternalFunction() 'без запуска функции во время компиляции? Это невозможно сделать во время компиляции, если вы не переключитесь на дженерики и не используете пример nvoigt. –

+0

Это не совсем правильно. Метод 'Add' напечатан, если эти функции не имеют правильного типа возврата, компилятор поймает его. – MarqueIV