Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 无法捕获泛型方法中构造函数的抛出_C# - Fatal编程技术网

C# 无法捕获泛型方法中构造函数的抛出

C# 无法捕获泛型方法中构造函数的抛出,c#,C#,我无法捕获以下代码中的异常: internal class Program { private class Wat { public Wat() { throw new Exception("how do i exception"); } } private static T BreakIt<T>() where T : new() { return new T(); }

我无法捕获以下代码中的异常:

internal class Program {
    private class Wat {
        public Wat() {
            throw new Exception("how do i exception");
        }
    }

    private static T BreakIt<T>() where T : new() {
        return new T();
    }

    private static void Main(string[] args) {
        try {
            BreakIt<Wat>();
        } catch(Exception e) {
            Console.WriteLine("it broke: " + e.Message);
        }
    }
}
内部类程序{
私人舱{
公共厕所{
抛出新异常(“如何处理异常”);
}
}
私有静态T BreakIt(),其中T:new(){
返回新的T();
}
私有静态void Main(字符串[]args){
试一试{
打破它();
}捕获(例外e){
Console.WriteLine(“它坏了:+e.Message”);
}
}
}
这也不起作用:

internal class Program {
    private class Wat {
        public Wat() {
            throw new Exception("how do i exception");
        }
    }

    private static T BreakIt<T>() where T : new() {
        try {
            return new T();
        } catch(Exception e) {
            Console.WriteLine("it broke: " + e.Message);
            return null;
        }
    }

    private static void Main(string[] args) {
        BreakIt<Wat>();
    }
}
内部类程序{
私人舱{
公共厕所{
抛出新异常(“如何处理异常”);
}
}
私有静态T BreakIt(),其中T:new(){
试一试{
返回新的T();
}捕获(例外e){
Console.WriteLine(“它坏了:+e.Message”);
返回null;
}
}
私有静态void Main(字符串[]args){
打破它();
}
}
但是,当未从构造函数引发异常时,它会起作用:

internal class Program {
    private class Wat {
        public void Break() {
            throw new Exception("how do i exception");
        }
    }

    private static T BreakIt<T>() where T : Wat, new() {
        T t = new T();
        t.Break();
        return t;
    }

    private static void Main(string[] args) {
        try {
            BreakIt<Wat>();
        } catch(Exception e) {
            Console.WriteLine("it broke: " + e.Message);
        }
    }
}
内部类程序{
私人舱{
公共空间中断(){
抛出新异常(“如何处理异常”);
}
}
私有静态T BreakIt(),其中T:Wat,new(){
T=新的T();
t、 Break();
返回t;
}
私有静态void Main(字符串[]args){
试一试{
打破它();
}捕获(例外e){
Console.WriteLine(“它坏了:+e.Message”);
}
}
}

这在调试和发布模式下都会发生。我的游戏是用一种通用的方法开始的,它完成了所有的设置,我正在尝试为我的crash reporter捕获所有未处理的异常。

如果这只发生在游戏框架内,可能与此有关


也许框架使用任务来分配工作。调试器停止后,您可以继续执行吗?

我认为这是因为它实际上在后台创建了一个不同的异常,因此您的异常会被框架代码而不是异常处理程序捕获

在.NET中,您不能直接调用泛型类型参数[1]上的方法,因此

public static T New<T>() where T : new()
{
  return new T();
}
publicstatict New(),其中T:New()
{
返回新的T();
}
实际上编译为

public static T New<T>() where T : new()
{
    if (default(T) != null)
    {
        return default(T);
    }
    return Activator.CreateInstance<T>();
}
publicstatict New(),其中T:New()
{
如果(默认值(T)!=null)
{
返回默认值(T);
}
返回Activator.CreateInstance();
}
(在释放模式下)。
Activate
类显然使用了反射,反射处理原始异常并抛出一个
TargetInvocationException


[1] 您可以使用ilasm.exe编译IL代码,但.NET和Mono将分别在加载方法或周围类型时引发异常。

所有这三种方法都有效(如果在第二个示例中使用
返回默认值(T)
替换
返回null
)。他们都打印出它坏了:…。如果您正在从VS进行调试,您可能需要在
Main
的末尾放置一个
Console.ReadKey()
,以便查看输出。请告诉我们您认为无法捕获这些异常的原因。你如何验证你是否抓住了他们?代码实际上是有效的(除了代码>返回NULL;在中间示例中,)。我有一些代码将保持它打开,我把它放在外面,因为我认为最好是给出最短的片段来复制它。对我来说,例外情况是,VS2013和.NET 4.5尝试使用CTRL-F5运行它。。。。visual studio可能只是在捕获异常之前向您显示该异常,因为您正在调试。Ctrl-F5在没有调试的情况下运行,因此您可以确定发生了什么。@p.s.w.g很抱歉,我的原始代码有Wat约束,该约束使返回空值有效。框架是我自己的,它不使用任务。它也发生在一个完全不同的项目中,我的问题中提供的代码与我的框架无关哇,我不知道发生了什么。因此,与直接使用实际构造函数相比,
new T()
的成本肯定要高得多吗?谢谢,再加上@JohnGibb关于不附加调试器的评论,使我意识到发生了什么。@JohnGibb是的,肯定是的(但总的来说可能没有多大意义)。对泛型类型参数没有静态调用也是.NET上常用函数语言的主要问题。F#通过静态泛型(afaik)为每个类型组合创建函数的新副本或直接内联它来解决这个问题。它避免了反射减慢,但缺点是不可能在运行时绑定它们。@JohnGibb需要注意的是,这是(afaik)对泛型的唯一异常昂贵的调用。虚拟调用使用声明它们的类型进行绑定,多态性限制为使用泛型类型参数。(这也会在运行时透明地克隆值类型的方法。)