惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Palo Alto Networks Blog
T
The Blog of Author Tim Ferriss
Engineering at Meta
Engineering at Meta
博客园_首页
博客园 - 三生石上(FineUI控件)
G
Google Developers Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 【当耐特】
Microsoft Security Blog
Microsoft Security Blog
P
Privacy & Cybersecurity Law Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
S
Secure Thoughts
爱范儿
爱范儿
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
H
Help Net Security
The Cloudflare Blog
Recorded Future
Recorded Future
Attack and Defense Labs
Attack and Defense Labs
J
Java Code Geeks
O
OpenAI News
T
Tor Project blog
B
Blog RSS Feed
D
Darknet – Hacking Tools, Hacker News & Cyber Security
PCI Perspectives
PCI Perspectives
V
Visual Studio Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
A
About on SuperTechFans
www.infosecurity-magazine.com
www.infosecurity-magazine.com
W
WeLiveSecurity
Cyberwarzone
Cyberwarzone
云风的 BLOG
云风的 BLOG
Security Latest
Security Latest
S
Schneier on Security
Know Your Adversary
Know Your Adversary
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
Vulnerabilities – Threatpost
D
DataBreaches.Net
宝玉的分享
宝玉的分享
T
Troy Hunt's Blog
V
V2EX
Cisco Talos Blog
Cisco Talos Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
美团技术团队
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Latest news
Latest news
量子位
Microsoft Azure Blog
Microsoft Azure Blog

博客园 - smalldust

NTT大规模网络故障 亲手焙制一个极其简单但却极其实用的Reflector插件 关于园子里讨论的软件的追求的杂谈 Reflector保护方法初探 .Net 2.0 原汁原味读取注册表 为什么我不用IE7和FireFox 给.Net程序员的PInvoke Tips [2]: Are Strings Immutable? 给.Net程序员的PInvoke Tips [1]: String is Sometimes an Integer CLR Team程序员出的难题,有兴趣的朋友不妨挑战一下 - smalldust - 博客园 Google Trends发布 也谈用反射实现Enum→String映射:一种重视性能的方法 针对个例的、社区性的维基系统设想(草稿) 数学的思考方式 VS 程序的思考方式 WinForm程序启动时不显示主窗体的实现方法 C#程序模拟鼠标操作 [Simulate Mouse Movement and Click Programmatically] 如何在C#中获取“当前目录” Windows Vista将推迟到2007年1月发布 .Net 2.0实例学习:WebBrowser页面与WinForm交互技巧 使用关键字作为自定义标识符
除了Exception,你还能throw什么?
smalldust · 2006-06-21 · via 博客园 - smalldust

用惯了C#,VB.Net的人,可能很习惯用下面的格式来捕获所有的异常:

try {
    
//Some code
}
catch (System.Exception ex) {
    System.Console.Write(
"Error!");
}

这条语句能捕获所有种类的异常吗?显然,这条语句捕获的是System.Exception,以及所有继承自它的类。
也就是说,如果你抛出了一个不是继承自System.Exception的对象,该语句就无法捕获。

抛出不是异常的异常……这种不兼容CLS的事情,可能吗?
答案是,在1.x当中是可能的。

在C++当中,我们可以用 throw "Error!" 这样的语句抛出一个字符串;
在IL当中,我们可以用下面的方式,抛出任意形式的异常:

.assembly ThrowerLib { }

.

class public Thrower {
    .method 
static public void Start( ) {
        ldstr 
"Oops"
        
throw
        ret
    }
}

所以,在.Net 1.x当中,经常使用下面这种最保险的方式:

try
{
    
//Some code
}
catch(System.Exception ex)
{
    System.Console.WriteLine(
"System.Exception error: " + ex.Message);
}
catch
{
    System.Console.WriteLine(
"Non System.Exception based error.);
}

但是,在.Net2.0当中,为了确保跨语言的兼容性,CLR会自动将不是继承自System.Exception的异常包裹在RuntimeWrappedException对象中;这样的结果就是,本文中第一个例子中的代码可以捕获所有类型的异常了。

同时,为了保证和1.x版本的兼容性,.Net 2.0提供了RuntimeCompatibilityAttribute类,指定CLR不要对异常进行包装:

[assembly:System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows = false)]

附:测试用代码(运行于.Net 2.0)

1,抛出字符串异常的IL代码,用ilasm /DLL编译

// ThrowerLib.il
.assembly ThrowerLib { }

.

class public Thrower {
    .method 
static public void ThrowException( ) {
        ldstr 
"ThrowException exception from the IL world!"
        newobj instance 
void [mscorlib]System.Exception::.ctor(string)
        
throw
        ret
    }

    .method 

static public void ThrowString( ) {
        ldstr 
"Weird exception!"
        
throw
        ret
    }
}

2,测试用C#代码,要添加对上面的DLL的引用

[assembly: System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows = false)]namespace ThrowerExample
{
    
class ThrowerHarness
    {
        
static void Main(string[] args)
        {
            
try
            {
                Thrower.ThrowException();
            }
            
catch (System.Exception ex)
            {
                System.Console.WriteLine(
"System.Exception error: " + ex.Message);
            }
            
catch 
            {
                System.Console.WriteLine(
"Non System.Exception based error.");
            }
try
            {
                Thrower.ThrowString();
            }
            
catch (System.Exception ex)
            {
                System.Console.WriteLine(
"System.Exception error: " + ex.Message);
            }
            
catch
            {
                System.Console.WriteLine(
"Non System.Exception based error.");
            }
        }
    }
}

执行结果是,第一个异常将被catch(System.Exception ex){}捕获;第二个异常由于catch(System.Exception ex){}无法捕获,将落到catch{}中。

如果把第一行的属性去掉,编译时将出现下面的警告:
warning CS1058: A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a System.Runtime.CompilerServices.RuntimeWrappedException

继续执行的话,两个异常都将被catch(System.Exception ex){}捕获,不会有任何异常落到catch{}当中