#c# #generics #static
#c# #общие сведения #статические
Вопрос:
У меня есть универсальный класс, который помогает мне выполнять проверки значений аргументов:
internal sealed class Argument<T>
where T : class
{
private void TraceAndThrow(Exception ex)
{
new InternalTraceHelper<T>().WriteError(ex);
throw ex;
}
internal void ThrowNull(object value, string argName)
{
if (ReferenceEquals(value, null))
{
TraceAndThrow(new ArgumentNullException(argName));
}
}
internal void ThrowIf(bool condition, string argName)
{
if (condition)
{
TraceAndThrow(new ArgumentException(null, argName));
}
}
internal void ThrowNotInEnum(Type enumType, object value)
{
if (!Enum.IsDefined(enumType, value))
{
TraceAndThrow(new ArgumentOutOfRangeException(Resources.ArgEnumIllegalVal.InvariantFormat(value)));
}
}
}
Но когда я пытаюсь использовать его со статическим классом:
internal static class Class1
{
private static Argument<Class1> _arg;
}
Я получил эту ошибку (при компиляции):
статические типы не могут использоваться в качестве аргументов типа
Что я делаю не так?
Ответ №1:
Это сделано намеренно.
Статические классы пытаются предотвратить ненадлежащее использование, поэтому почти во всех ситуациях вы не можете использовать их в ситуациях, когда вам обычно нужен экземпляр типа … и который включает аргументы типа.
Смотрите раздел «Статические классы» спецификации C # 6 для очень ограниченного набора ситуаций, в которых вы можете ссылаться на статические типы классов.
Комментарии:
1. Выполнение моих статических классов нестатическими, но с частным конструктором выполнит эту работу? Таким образом, никто не может создать его экземпляр, но он нестатичен. Это хороший способ выполнить это? (Спасибо за раздел, я его прочитал)
2. @Arnaud F.: Ну, это бы сработало — но для чего вы используете аргумент типа? Какой в этом смысл? Похоже, что это используется только
InternalTraceHelper
, и мы не знаем, на что это похоже.3.
InternalTraceHelper
действительноTrace.Write()
, тип аргумента используется для определения категории трассировки. Может быть заменен наTrace.WriteLine("a message", typeof(T).FullName); // Where T = Class1
4. @Arnaud F.: Похоже, вам, возможно, нужна не универсальная версия InternalTraceHelper, которая вместо этого принимает
Type
. На самом деле, вы могли бы сделать весь класс неуниверсальным, просто используя универсальный метод, чтобы упростить создание:InternalTraceHelper.Create<Foo>
вызывал бы,new InternalTraceHelper(typeof(T))
гдеT
— параметр типа для метода.5. Большое спасибо за подсказку Master!
Ответ №2:
Обобщения работают только с экземплярами, а не со статическими классами.
Комментарии:
1. Есть ли обходной путь? Как я могу этим управлять? Я бы не стал проверять «вручную» в статических классах и использовать
Argument<T>
в нестатическом…2. Нет, ничего другого, кроме использования
System.Type
.3. @Arnaud, вы не можете передавать статические типы в качестве аргументов, поэтому я не понимаю, когда вы вообще захотите иметь
Argument<StaticType>
, если только меня не вводит в заблуждение ваше название класса.4. Выполнение моих статических классов нестатическими, но с частным конструктором выполнит эту работу? Таким образом, никто не может создать его экземпляр, но он нестатичен. Это хороший способ выполнить это?
5. да, это определенно информативный ответ. почему вы потрудились написать такой длинный текст?
Ответ №3:
Поскольку статические классы не могут быть созданы, они никогда не смогут создаваться Argument<T>
со статическим типом.
Комментарии:
1. Это неверно. ILogger<T> — это пример, когда класс становится категорией, используемой регистратором при отправке диагностики. Это глупое правило.
2. @Quarkly, ты нашел способ обойти это? рассматриваю возможность просто сделать класс нестатическим сейчас
Ответ №4:
Что вы делаете неправильно, так это используете статический тип в качестве аргумента универсального типа.
Ответ №5:
Поскольку статические классы не будут иметь членов экземпляра, меня беспокоит, что я собираюсь с ними делать.
Я считаю, что, поскольку вы не можете использовать статические классы в качестве универсальных аргументов, я считаю, что вам нужно сделать это с помощью методов расширения вместо универсального класса.