interface IExecutor
{
void Execute();
}
class Executor2<T> where T : IExecutor
{
public void Execute()
{
var ex = (T)Activator.CreateInstance(typeof(T));
ex.Execute();
}
}
这是一个采访中的问题。他们告诉我,有时这个代码会掉落(引起异常),并且至少有3个原因可能导致问题。不知道有什么例外。但方法Execute
创建良好,实现没有错误。
有人对此提出建议吗?
编辑:至少有3个原因可能会导致问题。这些原因是什么?
答案 0 :(得分:4)
从表面上看,我可以看到一些问题。
要解释2:您在类定义中使用T
上的约束指定类型IExecutor
,但是您在方法级别定义了另一个类型T
而没有约束。这不会编译。
如果我修复此问题并从方法中删除<T>
定义,我可以看到它失败的一些原因而没有太多警告:
ex
为空。T
没有定义公共无参数构造函数。T
。雅库布发现:
T
可以是一个接口(没有构造函数)。T
可以是抽象类,这些不允许直接创建实例。第一个可以防止使用空检查if (ex != null)
,第二个可以防止使用另一个通用约束new()
:
class Executor2<T> where T : IExecutor, new()
{
}
显然,您还可以修改代码以包含异常日志记录。这可能有助于弄清楚实际问题的内容,而不仅仅是在黑暗中刺伤:
public void Execute<T>()
{
try
{
var ex = (T)Activator.CreateInstance(typeof(T));
ex.Execute();
}
catch (Exception ex)
{
Log(ex); // Mystical logging framework.
throw;
}
}
考虑到我不理解这个问题,这是我可以拼凑的唯一答案。
如果我在接受采访时被问到这个问题,我可能会说我无法命名所有3,但我知道如何更改代码以使其更易于维护并告诉我出了什么问题。然后我可能会走路去寻找毫无意义的面试问题。
答案 1 :(得分:2)
T
可能是界面或抽象类 - 您无法创建它们的实例,或T
没有无参数构造
此外,var ex = (T)Activator.CreateInstance(typeof(T));
可以重写为var ex = Activator.CreateInstance<T>();
答案 2 :(得分:2)
是否假设T的设计没有错误?我的意思是,如果T定义了一个执行Bad Stuff的静态构造函数,那么T的类型初始化将失败,如果它没有无参数构造函数,则会出现不同的异常。
就此而言,如果T定义了一个无参数的构造函数,它将失败,那么它也会被破坏。
此外,如果类型具有私有构造函数,您将收到错误。或者,如果类型继承自将导致TypeInitialisationException的类型
[编辑]
试试这个:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try {
new Executor2<IExecutor>().Execute();
}
catch { Console.WriteLine("Failed IExecutor"); }
try { new Executor2<AbstractExecutorWithImpl>().Execute(); }
catch { Console.WriteLine("Failed AbstractExecutorWithImpl"); }
try { new Executor2<AbstractExecutorWithNoImpl>().Execute(); }
catch { Console.WriteLine("Failed AbstractExecutorWithNoImpl"); }
try { new Executor2<ConcreteExecutor>().Execute(); }
catch { Console.WriteLine("Failed ConcreteExecutor"); }
try { new Executor2<DerivedExecutor>().Execute(); }
catch { Console.WriteLine("Failed DerivedExecutor"); }
try { new Executor2<DerivedExecutorWithBadConstr>().Execute(); }
catch { Console.WriteLine("Failed DerivedExecutorWithBadConstr"); }
try { new Executor2<DerivedExecutorWithPrivateConstr>().Execute(); }
catch { Console.WriteLine("Failed DerivedExecutorWithPrivateConstr"); }
try { new Executor2<DerivedExecutorWithPublicBadConstr>().Execute(); }
catch { Console.WriteLine("Failed DerivedExecutorWithPublicBadConstr"); }
Console.ReadLine();
}
}
interface IExecutor
{
void Execute();
}
abstract class AbstractExecutorWithImpl : IExecutor
{
public void Execute()
{
Console.Write("Executing AbstractExecutorWithImpl ");
}
}
abstract class AbstractExecutorWithNoImpl : IExecutor
{
public abstract void Execute();
}
class ConcreteExecutor : IExecutor
{
public void Execute()
{
Console.WriteLine("Executing ConcreteExecutor");
}
}
class DerivedExecutor : AbstractExecutorWithNoImpl
{
public override void Execute()
{
Console.WriteLine("Executing DerivedExecutor");
}
}
class DerivedExecutorWithBadConstr : IExecutor
{
static DerivedExecutorWithBadConstr() { throw new Exception("Static initialisation Exception"); }
public void Execute()
{
Console.WriteLine("Executing DerivedExecutorWithBadConstr");
}
}
class DerivedExecutorWithPrivateConstr : DerivedExecutor
{
private DerivedExecutorWithPrivateConstr() { }
}
class DerivedExecutorWithPublicBadConstr : DerivedExecutorWithBadConstr
{
public DerivedExecutorWithPublicBadConstr() : base() { }
}
class Executor2<T> where T : IExecutor
{
public void Execute()
{
var ex = (T)Activator.CreateInstance(typeof(T));
ex.Execute();
}
}
}