code_junkie

Casting vs using the 'as' keyword in the CLR

Nov 13th, 2011
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.00 KB | None | 0 0
  1. public interface IMyInterface
  2. {
  3. void AMethod();
  4. }
  5.  
  6. public class MyClass : IMyInterface
  7. {
  8. public void AMethod()
  9. {
  10. //Do work
  11. }
  12.  
  13. // Other helper methods....
  14. }
  15.  
  16. public class Implementation
  17. {
  18. IMyInterface _MyObj;
  19. MyClass _myCls1;
  20. MyClass _myCls2;
  21.  
  22. public Implementation()
  23. {
  24. _MyObj = new MyClass();
  25.  
  26. // What is the difference here:
  27. _myCls1 = (MyClass)_MyObj;
  28. _myCls2 = (_MyObj as MyClass);
  29. }
  30. }
  31.  
  32. // Bad code - checks type twice for no reason
  33. if (randomObject is TargetType)
  34. {
  35. TargetType foo = (TargetType) randomObject;
  36. // Do something with foo
  37. }
  38.  
  39. // This will throw an exception if randomObject is non-null and
  40. // refers to an object of an incompatible type. The cast is
  41. // the best code if that's the behaviour you want.
  42. TargetType convertedRandomObject = (TargetType) randomObject;
  43.  
  44. TargetType convertedRandomObject = randomObject as TargetType;
  45. if (convertedRandomObject != null)
  46. {
  47. // Do stuff with convertedRandomObject
  48. }
  49.  
  50. TargetType? convertedRandomObject = randomObject as TargetType?;
  51. if (convertedRandomObject != null)
  52. {
  53. // Do stuff with convertedRandomObject.Value
  54. }
  55.  
  56. using System;
  57. using System.Diagnostics;
  58. using System.Linq;
  59.  
  60. class Test
  61. {
  62. const int Size = 30000000;
  63.  
  64. static void Main()
  65. {
  66. object[] values = new object[Size];
  67. for (int i = 0; i < Size - 2; i += 3)
  68. {
  69. values[i] = null;
  70. values[i + 1] = "x";
  71. values[i + 2] = new object();
  72. }
  73. FindLengthWithIsAndCast(values);
  74. FindLengthWithIsAndAs(values);
  75. FindLengthWithAsAndNullCheck(values);
  76. }
  77.  
  78. static void FindLengthWithIsAndCast(object[] values)
  79. {
  80. Stopwatch sw = Stopwatch.StartNew();
  81. int len = 0;
  82. foreach (object o in values)
  83. {
  84. if (o is string)
  85. {
  86. string a = (string) o;
  87. len += a.Length;
  88. }
  89. }
  90. sw.Stop();
  91. Console.WriteLine("Is and Cast: {0} : {1}", len,
  92. (long)sw.ElapsedMilliseconds);
  93. }
  94.  
  95. static void FindLengthWithIsAndAs(object[] values)
  96. {
  97. Stopwatch sw = Stopwatch.StartNew();
  98. int len = 0;
  99. foreach (object o in values)
  100. {
  101. if (o is string)
  102. {
  103. string a = o as string;
  104. len += a.Length;
  105. }
  106. }
  107. sw.Stop();
  108. Console.WriteLine("Is and As: {0} : {1}", len,
  109. (long)sw.ElapsedMilliseconds);
  110. }
  111.  
  112. static void FindLengthWithAsAndNullCheck(object[] values)
  113. {
  114. Stopwatch sw = Stopwatch.StartNew();
  115. int len = 0;
  116. foreach (object o in values)
  117. {
  118. string a = o as string;
  119. if (a != null)
  120. {
  121. len += a.Length;
  122. }
  123. }
  124. sw.Stop();
  125. Console.WriteLine("As and null check: {0} : {1}", len,
  126. (long)sw.ElapsedMilliseconds);
  127. }
  128. }
  129.  
  130. int value;
  131. if (int.TryParse(text, value))
  132. {
  133. value = int.Parse(text);
  134. // Use value
  135. }
  136.  
  137. _myCls2 = _myObj is MyClass ? (MyClass)_myObj : null;
  138.  
  139. public class MyClass
  140. {
  141. public static void Main()
  142. {
  143. // Call the 2 methods
  144. }
  145.  
  146. public void DirectCast(Object obj)
  147. {
  148. if ( obj is MyClass)
  149. {
  150. MyClass myclass = (MyClass) obj;
  151. Console.WriteLine(obj);
  152. }
  153. }
  154.  
  155.  
  156. public void UsesAs(object obj)
  157. {
  158. MyClass myclass = obj as MyClass;
  159. if (myclass != null)
  160. {
  161. Console.WriteLine(obj);
  162. }
  163. }
  164. }
  165.  
  166. .method public hidebysig instance void DirectCast(object obj) cil managed
  167. {
  168. // Code size 22 (0x16)
  169. .maxstack 8
  170. IL_0000: ldarg.1
  171. IL_0001: isinst MyClass
  172. IL_0006: brfalse.s IL_0015
  173. IL_0008: ldarg.1
  174. IL_0009: castclass MyClass
  175. IL_000e: pop
  176. IL_000f: ldarg.1
  177. IL_0010: call void [mscorlib]System.Console::WriteLine(object)
  178. IL_0015: ret
  179. } // end of method MyClass::DirectCast
  180.  
  181. .method public hidebysig instance void UsesAs(object obj) cil managed
  182. {
  183. // Code size 17 (0x11)
  184. .maxstack 1
  185. .locals init (class MyClass V_0)
  186. IL_0000: ldarg.1
  187. IL_0001: isinst MyClass
  188. IL_0006: stloc.0
  189. IL_0007: ldloc.0
  190. IL_0008: brfalse.s IL_0010
  191. IL_000a: ldarg.1
  192. IL_000b: call void [mscorlib]System.Console::WriteLine(object)
  193. IL_0010: ret
  194. } // end of method MyClass::UsesAs
  195.  
  196. public class Foo
  197. {
  198. public string Value;
  199.  
  200. public static explicit operator string(Foo f)
  201. {
  202. return f.Value;
  203. }
  204.  
  205. }
  206.  
  207. public class Example
  208. {
  209. public void Convert()
  210. {
  211. var f = new Foo();
  212. f.Value = "abc";
  213.  
  214. string cast = (string)f;
  215. string tryCast = f as string;
  216. }
  217. }
  218.  
  219. if (randomObject is TargetType)
  220. {
  221. TargetType foo = randomObject as TargetType;
  222. // Do something with foo
  223. }
  224.  
  225. TargetType convertedRandomObject = randomObject as TargetType;
  226. if (convertedRandomObject != null)
  227. {
  228. // Do stuff with convertedRandomObject
  229. }
  230.  
  231. IMyInterface = (IMyInterface)someobj;
Add Comment
Please, Sign In to add comment