НЕ делайте никогда выгода Throwable
или Error
, и Вы не должны обычно просто ловить дженерик Exception
также. Error
с обычно являются вещами, с которых не могут возможно восстановиться самые разумные программы. Если Вы знаете то, что продолжается, Вы могли бы быть в состоянии восстановиться с одной определенной ошибки, но в этом случае, необходимо поймать только [1 117] что одна конкретная ошибка и не все ошибки в целом.
серьезное основание А не поймать Error
из-за [1 115] ThreadDeath
. ThreadDeath
довольно нормальное возникновение, которое может теоретически быть брошено отовсюду (другие процессы как сама JVM могут генерировать его), и смысл его должен уничтожить Ваш поток. ThreadDeath
явно Error
, а не Exception
, потому что слишком много людей ловят весь Exception
с. Если бы когда-нибудь необходимо было ловить ThreadDeath
, то Вы должны перебросок это так, чтобы Ваш поток на самом деле умер.
, Если Вы управляете источником, он должен, вероятно, быть реструктурирован для броска Exception
, а не Error
. Если Вы не делаете, необходимо, вероятно, позвать поставщика и жаловаться. Error
с должна быть зарезервирована только для вещей, которые являются терминальными без возможного способа восстановиться от них.
Вы можете попробовать что-то вроде этого:
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
}
}
Нет. Если TResult не имеет ограничений, то это может быть любая старая вещь. Если ваш вспомогательный метод не может принимать какие-либо старые вещи, вам нужно получить лучший вспомогательный метод. Интерфейс требует, чтобы вы предоставляли больше услуг, чем может предоставить ваш помощник, поэтому вам придется выполнить работу по предоставлению этой услуги.
Вам нужно будет добавить ограничения типа к вашему универсальному методу:
public TResult Execute<TResult>(...) where TResult: MyBaseClass, new() {
return something.Foo<TResult>();
}
Ой ... у вас проблема. Невозможно вызвать 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();
}
Обновление: ответ отражения может быть лучшим подходом, если это сработает.
Измените Foo, чтобы проверить ограничения во время выполнения:
public T Foo<T>() {
if (!typeof(T).IsAssignableFrom(typeof(MyBaseClass))
|| !typeof(T).GetConstructor(...))
throw new System.NotImplementedException();
...
}
Общие ограничения проверяются во время компиляции, поэтому они не могут быть основаны на условиях выполнения.