универсальные ограничения переменной типа и интерфейсы

НЕ делайте никогда выгода Throwable или Error, и Вы не должны обычно просто ловить дженерик Exception также. Error с обычно являются вещами, с которых не могут возможно восстановиться самые разумные программы. Если Вы знаете то, что продолжается, Вы могли бы быть в состоянии восстановиться с одной определенной ошибки, но в этом случае, необходимо поймать только [1 117] что одна конкретная ошибка и не все ошибки в целом.

серьезное основание А не поймать Error из-за [1 115] ThreadDeath . ThreadDeath довольно нормальное возникновение, которое может теоретически быть брошено отовсюду (другие процессы как сама JVM могут генерировать его), и смысл его должен уничтожить Ваш поток. ThreadDeath явно Error, а не Exception, потому что слишком много людей ловят весь Exception с. Если бы когда-нибудь необходимо было ловить ThreadDeath, то Вы должны перебросок это так, чтобы Ваш поток на самом деле умер.

, Если Вы управляете источником, он должен, вероятно, быть реструктурирован для броска Exception, а не Error. Если Вы не делаете, необходимо, вероятно, позвать поставщика и жаловаться. Error с должна быть зарезервирована только для вещей, которые являются терминальными без возможного способа восстановиться от них.

5
задан kolosy 14 September 2009 в 22:06
поделиться

5 ответов

Вы можете попробовать что-то вроде этого:

public TResult Execute<TResult>(...) 
{
  if (typeof(TResult) is MyBaseClass)
  {
      Type mytype = typeof(TResult);
      MethodInfo method = typeof({TypewhereFoo<>IsDeclared}).GetMethod("Foo");
      MethodInfo generic = method.MakeGenericMethod(myType);
      return (TResult)generic.Invoke(this, null);
  }
  else
  {
     // Throw here
  }
}
2
ответ дан 15 December 2019 в 06:30
поделиться

Нет. Если TResult не имеет ограничений, то это может быть любая старая вещь. Если ваш вспомогательный метод не может принимать какие-либо старые вещи, вам нужно получить лучший вспомогательный метод. Интерфейс требует, чтобы вы предоставляли больше услуг, чем может предоставить ваш помощник, поэтому вам придется выполнить работу по предоставлению этой услуги.

1
ответ дан 15 December 2019 в 06:30
поделиться

Вам нужно будет добавить ограничения типа к вашему универсальному методу:

public TResult Execute<TResult>(...) where TResult: MyBaseClass, new() {
  return something.Foo<TResult>();
}
0
ответ дан 15 December 2019 в 06:30
поделиться

Ой ... у вас проблема. Невозможно вызвать something.Foo (), поскольку у вас нет совместимого типа. Вы можете «взломать» это, создав тип «оболочки», совместимый с вызовом Foo (), а затем «разворачивать»:

    class MyNastyFix<T> : MyBaseClass
    {
        public T Unwrap()
        {
            //assert that T has the correct base type
            if (!typeof(T).IsSubclassOf(typeof(MyBaseClass)))
                throw new ArgumentException();
            //must use reflection to construct
            T obj = (T)typeof(T).InvokeMember(null, BindingFlags.CreateInstance, null, null, null);
            //cast to a type of MyBaseClass so we can copy our values
            MyBaseClass c = (MyBaseClass)(object)obj;
            c.SomeValue = this.SomeValue;
            return obj;
        }
    }

    public static TResult Execute<TResult>()
    {
        return something.Foo<MyNastyFix<TResult>>().Unwrap();
    }

Обновление: ответ отражения может быть лучшим подходом, если это сработает.

0
ответ дан 15 December 2019 в 06:30
поделиться

Измените Foo, чтобы проверить ограничения во время выполнения:

public T Foo<T>() {
    if (!typeof(T).IsAssignableFrom(typeof(MyBaseClass))
        || !typeof(T).GetConstructor(...))
        throw new System.NotImplementedException();
    ...
 }

Общие ограничения проверяются во время компиляции, поэтому они не могут быть основаны на условиях выполнения.

0
ответ дан 15 December 2019 в 06:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: