Запретить использование определенной иерархии типов для универсального параметра

Я начал этот вопрос с множества предыстории рассматриваемых типов; интерфейсы и обоснование архитектуры.

Затем я понял - «Это ТАК - делайте это простым и переходите к сути».

Итак, начнем.

У меня есть такой класс:

public class AGenericType<T> : AGenericTypeBase
{
  T Value { get; set; }
}

В таком случае .Net, конечно, позволяет мне сделать это:

AGenericType<AGenericType<int>> v;

Однако в контексте использования AGenericType делать это так же, как и ерунда делать это:

Nullable<Nullable<double>> v;

Я хочу ограничить этот универсальный тип, чтобы было невозможно создать такой экземпляр или даже объявить ссылку на тип, когда он T является производным из AGenericTypeBase - предпочтительно во время компиляции.

Интересно то, что Nullable Пример , который я привожу здесь , действительно генерирует ошибку компилятора. Но я не могу понять, как Nullable ограничивает T не- Nullable типами - поскольку Nullable - это структура, и единственное общее ограничение, которое я могу найти (даже в IL, который часто дает секреты компилятора, например, с делегатами), это , где T: struct . Итак, я думаю, что это должно быть хакерство компилятора ( EDIT: см. Ответ @Daniel Hilgarth + комментарии ниже, чтобы немного изучить это ). Взлом компилятора, который я, конечно, не могу повторить!

В моем собственном сценарии IL и C # не допускают ограничение отрицательного утверждения, подобное этому:

public class AGenericType<T> : where !T:AGenericTypeBase

(обратите внимание на '!' в ограничении)

Но какую альтернативу я могу использовать?

Я подумал о двух:

1) Исключение времени выполнения, созданное в конструкторе AGenericType :

public AGenericType(){
  if(typeof(AGenericBase).IsAssignableFrom(typeof(T)))
    throw new InvalidOperationException();
}

Однако это на самом деле не отражает природы ошибки - потому что проблема заключается в общем параметре и, следовательно, во всем типе; не только этот экземпляр.

2) Вместо этого то же исключение времени выполнения, но сгенерированное в статическом инициализаторе для AGenericType :

static AGenericType(){
  if(typeof(AGenericBase).IsAssignableFrom(typeof(T)))
    throw new InvalidOperationException();
}

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

Для меня это явный случай для 'отрицательное утверждение' svn cp -m 'Создание тестовой ветки' svn: // svnrepo / hellosite svn: // svnrepo / hellosite2

Итак, для перехода мне нужно каждый раз указывать полный URL удаленного репозитория. Но:

  • Рабочая копия связана с одним удаленным репозиторием. Даже переключение svn считается продвинутой «хирургической» операцией.
  • Разветвление удаленных URL-адресов в том же репозитории, что и рабочая копия, всегда имеет место (по крайней мере, мне никогда не приходилось выполнять ветвление в репозитории, который полностью не связан с текущим).
  • Копирование между репозиториями не поддерживается (верно?).
  • Информация об удаленном репозитории доступна: см. Svn info.

Так почему же я должен вводить полные URL-адреса каждый раз? !! Или я что-то упускаю? Есть ли какой-то ярлык, который позволяет ссылаться на текущий удаленный репозиторий? Что-то типа svn cp -m 'Создание тестовой ветви' // hellosite // hellosite2

26
задан Petr Gladkikh 18 May 2011 в 13:32
поделиться