2 // System.Diagnostics.StackTrace.cs
5 // Alexander Klyubin (klyubin@aqris.com)
6 // Dietmar Maurer (dietmar@ximian.com)
12 using System
.Reflection
;
13 using System
.Threading
;
14 using System
.Runtime
.CompilerServices
;
15 using System
.Collections
;
17 namespace System
.Diagnostics
{
20 /// TODO: more information.
23 public class StackTrace
{
25 /// Uses a constant to define the number of methods that are
26 /// to be omitted from the stack trace.
28 public const int METHODS_TO_SKIP
= 0;
31 /// Frames. First frame is the last stack frame pushed.
33 private StackFrame
[] frames
;
36 /// Initializes a new instance of the StackTrace class.
40 init_frames (METHODS_TO_SKIP
, false);
44 /// Initializes a new instance of the StackTrace class.
46 /// <param name="needFileInfo">
49 public StackTrace(bool needFileInfo
) {
50 init_frames (METHODS_TO_SKIP
, needFileInfo
);
54 /// Initializes a new instance of the StackTrace class
55 /// from the current location, in a caller's frame.
57 /// <param name="skipFrames">
58 /// The number of frames up the stack to start the trace
61 public StackTrace(int skipFrames
) {
62 init_frames (skipFrames
, false);
66 /// Initializes a new instance of the StackTrace class
67 /// from the current location, in a caller's frame.
69 /// <param name="skipFrames">
70 /// The number of frames up the stack to start the trace
73 /// <param name="needFileInfo">
76 public StackTrace(int skipFrames
, bool needFileInfo
) {
77 init_frames (skipFrames
, needFileInfo
);
80 void init_frames (int skipFrames
, bool needFileInfo
)
83 ArrayList al
= new ArrayList ();
87 while ((sf
= new StackFrame (skipFrames
, needFileInfo
)) != null &&
88 sf
.GetMethod () != null) {
94 frames
= (StackFrame
[])al
.ToArray (typeof (StackFrame
));
97 static StackFrame
[] get_trace (Exception e
, int skipFrames
, bool needFileInfo
)
102 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
103 extern static StackFrame
[] get_trace (Exception e
, int skipFrames
, bool needFileInfo
);
106 /// Initializes a new instance of the StackTrace class.
111 public StackTrace(Exception e
)
113 frames
= get_trace (e
, METHODS_TO_SKIP
, false);
117 /// Initializes a new instance of the StackTrace class,
118 /// using the provided exception object. The resulting stack
119 /// trace describes the stack at the time of the exception.
124 /// <param name="needFileInfo">
127 public StackTrace(Exception e
, bool needFileInfo
) {
128 frames
= get_trace (e
, METHODS_TO_SKIP
, needFileInfo
);
132 /// Initializes a new instance of the StackTrace class,
133 /// using the provided exception object. The resulting stack
134 /// trace describes the stack at the time of the exception.
139 /// <param name="skipFrames">
140 /// The number of frames up the stack to start the trace
143 public StackTrace(Exception e
, int skipFrames
) {
144 frames
= get_trace (e
, skipFrames
, false);
148 /// Initializes a new instance of the StackTrace class,
149 /// using the provided exception object. The resulting stack
150 /// trace describes the stack at the time of the exception.
155 /// <param name="skipFrames">
156 /// The number of frames up the stack to start the trace
159 /// <param name="needFileInfo">
162 public StackTrace(Exception e
, int skipFrames
, bool needFileInfo
) {
163 frames
= get_trace (e
, skipFrames
, needFileInfo
);
167 /// Initializes a new instance of the StackTrace class
168 /// containing a single frame.
170 /// <param name="frame">
171 /// The frame that the StackTrace object should contain.
173 public StackTrace(StackFrame frame
) {
174 this.frames
= new StackFrame
[1];
175 this.frames
[0] = frame
;
179 /// Initializes a new instance of the StackTrace class.
181 /// <param name="targetThread">
184 /// <param name="needFileInfo">
188 public StackTrace(Thread targetThread
, bool needFileInfo
) {
189 throw new NotImplementedException();
193 /// Holds the number of frames in the stack trace.
195 public virtual int FrameCount
{
197 return (frames
== null) ? 0 : frames
.Length
;
202 /// Gets the specified stack frame.
204 /// <param name="index">
205 /// The index of the stack frame requested.
208 /// The specified stack frame. Returns <code>null</code> if
209 /// frame with specified index does not exist in this stack
213 /// Stack frames are numbered starting at zero, which is the
214 /// last stack frame pushed.
216 public virtual StackFrame
GetFrame(int index
) {
217 if ((index
< 0) || (index
>= FrameCount
)) {
221 return frames
[index
];
225 /// Builds a readable representation of the stack trace.
228 /// A readable representation of the stack trace.
230 public override string ToString() {
232 for (int i
= 0; i
< FrameCount
; i
++) {
233 StackFrame frame
= GetFrame(i
);
234 result
+= "\n\tat " + FrameToString(frame
);
240 public override bool Equals(Object obj
) {
241 if ((obj
== null) || (!(obj
is StackTrace
))) {
245 StackTrace rhs
= (StackTrace
) obj
;
247 if (FrameCount
!= rhs
.FrameCount
) {
251 for (int i
= 0; i
< FrameCount
; i
++) {
252 if (!GetFrame(i
).Equals(rhs
.GetFrame(i
))) {
260 public override int GetHashCode() {
265 /// Converts single stack frame to string to be used in
268 /// <param name="frame">
269 /// Frame to convert.
272 /// A readable representation of stack frame for using
275 private static String
FrameToString(StackFrame frame
) {
276 MethodBase method
= frame
.GetMethod();
277 if (method
!= null) {
278 // Method information available
279 return method
.DeclaringType
.FullName
280 + "." + method
.Name
+ "()";
282 // Method information not available
283 return "<unknown method>";