做个游戏:设计代码生成特定的调用堆栈
前篇文章里我談了談String.Concat與StringBuilder的實現(xiàn),于是后來有個朋友回復(fù)到:“我發(fā)現(xiàn)StringBuilder里好像也用了String.Concat。在一次異常中,Exception的StackTrace顯示是先發(fā)生了String.Concat異常,然后再StringBuilder.Append。”不過經(jīng)過一些簡單的分析,我們會發(fā)現(xiàn)StringBuilder.Append方法的各個重載都沒有依賴(即調(diào)用)String.Concat方法,那么這樣的調(diào)用堆棧又是如何形成的呢?
展開答案
其實這并不困難,只要簡單“推理”一番便可。雖然StringBuilder的Append方法沒有依賴String.Concat方法,但這只能說明Append方法沒有直接調(diào)用String.Concat。然而,只要Append方法有機會調(diào)用到我們自定義的邏輯中,便可以由我們的邏輯調(diào)用Concat方法。這樣的方法可以是Append(object)重載:
public StringBuilder Append(object value) {if (value == null){return this;}return this.Append(value); }那么,我們的方法可以調(diào)用String.Concat方法,但又如何讓它拋出異常呢?很容易,因為String.Concat方法也有個Concat(object, object)重載會調(diào)用參數(shù)的ToString方法。不過,如果我們直接調(diào)用String.Concat方法也太不自然了些,相信之前那位朋友也不會這么做。但是,其實我們完全可以:
public class InBuilder {public override string ToString(){return "Hello" + new InConcat();} }public class InConcat {public override string ToString(){throw new Exception();} }static void Main() {var builder = new StringBuilder();builder.Append(new InBuilder()); }看InBuilder的ToString中,將一個字符串與另一個非字符串對象連接起來,而這個連接操作便會被編譯為String.Concat(object, object)方法:
.method public hidebysig virtual instance string ToString() cil managed {.maxstack 8L_0000: ldstr "Hello"L_0005: newobj instance void SimpleConsole.Program/InConcat::.ctor()L_000a: call string [mscorlib]System.String::Concat(object, object)L_000f: ret }于是執(zhí)行Main方法便會拋出一個異常,它的StackTrace便是:
at SimpleConsole.Program.InConcat.ToString() in ...at SimpleConsole.Program.InBuilder.ToString() in ...at SimpleConsole.Program.Main() in ... ...嘿嘿,我是不是很無聊?
轉(zhuǎn)載于:https://www.cnblogs.com/JeffreyZhao/archive/2009/12/04/stack-trace-with-StringBuilder-and-String-Concat.html
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的做个游戏:设计代码生成特定的调用堆栈的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2010:关于 Web 的 30 个预测
- 下一篇: 秒,微秒,毫秒