How would you call this dedication?
This book is dedicated to all who teach peace and resist violenceJavaScript: The Definitive Guide by David Flanagan
This book is dedicated to all who teach peace and resist violenceJavaScript: The Definitive Guide by David Flanagan
public class SingletonFoo : ObjectWithIdentifier { private static int instancesCount; private static PreciousResource preciousResource = new PreciousResource(); private static SingletonFoo instance = new SingletonFoo(); // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static SingletonFoo() { } private SingletonFoo() { instancesCount++; } public static SingletonFoo Instance { get { return instance; } } public void ManipulatePreciousResource() { // no need for locking, we are in a singleton! Console.WriteLine("{0} is accessing the resource {1}", this, preciousResource); preciousResource.Manipulate(); } public override string ToString() { return String.Format("{0} [instances count: {1}]", base.ToString(), instancesCount); } }For clarification here is ObjectWithIdentifier:
public class ObjectWithIdentifier { private Guid uniqueId = Guid.NewGuid(); public Guid UniqueId { get { return uniqueId; } } public override string ToString() { return String.Format("{0}, id: {1}", this.GetType().Name, uniqueId); } }ObjectWithIdentifier is only necessary for giving more meaningful output from the application.
public class PreciousResource : ObjectWithIdentifier { public void Manipulate() { //do something } }However, here comes the evil doer:
public static class EvilBar { const int REPEAT_COUNT = 2; public static void BeNice() { Console.WriteLine("Now I'm nice"); for (int i = 0; i < REPEAT_COUNT; i++) { SingletonFoo.Instance.ManipulatePreciousResource(); } } public static void BeEvil() { Console.WriteLine("Now I'm evil!"); for (int i = 0; i < REPEAT_COUNT; i++) { ((SingletonFoo) Activator.CreateInstance(typeof(SingletonFoo), true)).ManipulatePreciousResource(); } } }When EvilBar is nice we get following output:
Now I'm nice SingletonFoo, id: 7dbccd1c-4e74-4e1d-b762-104f4cbcb82b [instances count: 1] is accessing the resource PreciousResource, id: c2b4a8b7-80e8-46cf-b616-a3f45f0612d7 SingletonFoo, id: 7dbccd1c-4e74-4e1d-b762-104f4cbcb82b [instances count: 1] is accessing the resource PreciousResource, id: c2b4a8b7-80e8-46cf-b616-a3f45f0612d7But what happens if EvilBar is trully evil:
Now I'm evil! SingletonFoo, id: 5a829a65-580f-4cc2-b17b-2650f68e464b [instances count: 2] is accessing the resource PreciousResource, id: 8417a76b-a40b-4221-bd73-0b507ff059c9 SingletonFoo, id: 744eba58-9aa9-4ee2-97aa-ffd815c3832f [instances count: 3] is accessing the resource PreciousResource, id: 8417a76b-a40b-4221-bd73-0b507ff059c9We have three instances of our Singleton class. One for singleton and two instance created with Activator.
public static void BeUnwittlinglyEvil(SingletonFoo foo) { Console.WriteLine("Now I'm unwittingly evil"); Console.WriteLine("Foo before operations: {0}", foo); XmlSerializer serializer = new XmlSerializer(typeof(SingletonFoo)); StringBuilder serialized = new StringBuilder(); using (StringWriter sw = new StringWriter(serialized)) { serializer.Serialize(sw, foo); } SingletonFoo result; using (StringReader sr = new StringReader(serialized.ToString())) { result = (SingletonFoo) serializer.Deserialize(sr); } result.ManipulatePreciousResource(); }After executing the method EvilBar.BeUnwittlinglyEvil(SingletonFoo.Instance), we get following output:
Now I'm unwittingly evil Foo before operations: SingletonFoo, id: 5c4724bb-ac02-4300-9be6-70c86c5629fc [instances count: 1] SingletonFoo, id: 58612540-6d6a-458a-8c0c-1f723117f9b6 [instances count: 2] is accessing the resource PreciousResource, id: e7a55b7f-4e62-4d1f-878c-499ec0387a31The implementation looks weird, but that just an example what happens if someone serializes this class and then unserializes it. If the code is executed in different threads, you will run into synchronization issues.
1. A month with fewer than 28 days
2. stat("." ,&sb) == -1 (that is, can't access the current directory)
3. In C++: a = 2; b = 3; if (a + b != 5) exit(1);
4. A triangle with an interior angle sum \u8800 180°
5. A minute that doesn't have 60 seconds
6. In Java: (a + 1) <= a
1. September, 1752 had only 19 days. This was done to synchronize calendars as part of the Gregorian Reformation.
2. The directory could have been removed by another process, you might not have permission to read it, &sb might be invalid—you get the picture.
3. We sneakily didn't specify the types of a and b. Operator overloading might have defined +, =, or ! = to have unexpected behavior. Also, a and b may be aliases for the same variable, so the second assignment will overwrite the value stored in the first.
4. In non-Euclidean geometry, the sum of the angles of a triangle will not add up to 180°. Think of a triangle mapped on the surface of a sphere.
5. Leap minutes may have 61 or 62 seconds.
6. Overflow may leave the result of a + 1 negative (this can also happen in C and C++).
class TestClass { public void SomeMethod() { Console.WriteLine("doing something"); } public void SomeMethodWithArgs(int arg) { Console.WriteLine("doing something with arg {0}", arg); } public string SomeMethodWithArgsAndReturn(int arg, string str) { Console.WriteLine("again doing something"); return String.Format("result ({0} + {1} = <foobar>", arg, str); } public IEnumerable<int> SomeIteratorMethod() { int counter = 0; while (counter++ < 3) { yield return 2 * counter + 3; } } }When I look at SomeMethodWithArgsAndReturn, in reflector it looks like this:
public string SomeMethodWithArgsAndReturn(int arg, string str) { Console.WriteLine("again doing something"); return string.Format("result ({0} + {1} = <foobar>", arg, str); }Cool, huh?
public IEnumerable<int> SomeIteratorMethod() { <someiteratormethod>d__0 V_0 = new <someiteratormethod>d__0(-2); V_0.<>4__this = this; return V_0; }I also have a new class:
[CompilerGenerated] private sealed class <someiteratormethod>d__0 : IEnumerable<int>, IEnumerable, IEnumerator<int>, IEnumerator, IDisposable { // Fields private int <>1__state; private int <>2__current; public TestClass <>4__this; private int <>l__initialThreadId; public int <counter>5__1; // Methods [DebuggerHidden] public <someiteratormethod>d__0(int <>1__state); private bool MoveNext(); [DebuggerHidden] IEnumerator<int> IEnumerable<int>.GetEnumerator(); [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator(); [DebuggerHidden] void IEnumerator.Reset(); void IDisposable.Dispose(); // Properties int IEnumerator<int>.Current { [DebuggerHidden] get; } object IEnumerator.Current { [DebuggerHidden] get; } }I've hidden implementation but that's just an implementation of an iterator. However, that's a lot of code compared to my simple yield statement.
[Serializable] public class TraceAttribute : OnMethodBoundaryAspect { private void LogMethod(string beginning, MethodExecutionEventArgs eventArgs) { StringBuilder result = new StringBuilder(); result.Append("== "); result.Append(beginning); result.AppendFormat(" {0}.{1}(", eventArgs.Method.DeclaringType.Name, eventArgs.Method.Name); //imma charging mah oneliner ;) result.Append(String.Join(",", (from arg in eventArgs.GetReadOnlyArgumentArray() ?? new object[0] select String.Format("[{0}]", Convert.ToString(arg))).ToArray())); result.AppendFormat(") -> [{0}]", eventArgs.ReturnValue); result.Append(" =="); Console.WriteLine(result.ToString()); } public override void OnEntry(MethodExecutionEventArgs eventArgs) { LogMethod("Entering", eventArgs); } public override void OnExit(MethodExecutionEventArgs eventArgs) { LogMethod("Leaving", eventArgs); } }I've added TraceAttribute to SomeMethodWithArgsAndReturn:
[TraceAttribute] public string SomeMethodWithArgsAndReturn(int arg, string str) { Console.WriteLine("again doing something"); return String.Format("result ({0} + {1} = <foobar>", arg, str); }In the end when I run my app with:
(new TestClass()).SomeMethodWithArgsAndReturn(11, "twelve");I get nice output:
== Entering TestClass.SomeMethodWithArgsAndReturn([11],[twelve]) -> [] == == Leaving TestClass.SomeMethodWithArgsAndReturn([11],[twelve]) -> [result (11 + twelve = <foobar>] ==But now my simple method in reflector looks completely different:
public string SomeMethodWithArgsAndReturn(int arg, string str) { string ~returnValue~1; MethodExecutionEventArgs ~laosEventArgs~4; try { object[] ~arguments~3 = new object[] { arg, str }; ~laosEventArgs~4 = new MethodExecutionEventArgs(<>AspectsImplementationDetails_1.~targetMethod~1, this, ~arguments~3); <>AspectsImplementationDetails_1.PostSharpTest.TraceAttribute~1.OnEntry(~laosEventArgs~4); if (~laosEventArgs~4.FlowBehavior == FlowBehavior.Return) { return (string) ~laosEventArgs~4.ReturnValue; } Console.WriteLine("again doing something"); string CS$1$0000 = string.Format("result ({0} + {1} = <foobar>", arg, str); ~returnValue~1 = CS$1$0000; ~laosEventArgs~4.ReturnValue = ~returnValue~1; <>AspectsImplementationDetails_1.PostSharpTest.TraceAttribute~1.OnSuccess(~laosEventArgs~4); ~returnValue~1 = (string) ~laosEventArgs~4.ReturnValue; } catch (Exception ~exception~2) { ~laosEventArgs~4.Exception = ~exception~2; <>AspectsImplementationDetails_1.PostSharpTest.TraceAttribute~1.OnException(~laosEventArgs~4); switch (~laosEventArgs~4.FlowBehavior) { case FlowBehavior.Continue: return ~returnValue~1; case FlowBehavior.Return: return (string) ~laosEventArgs~4.ReturnValue; } throw; } finally { ~laosEventArgs~4.ReturnValue = ~returnValue~1; <>AspectsImplementationDetails_1.PostSharpTest.TraceAttribute~1.OnExit(~laosEventArgs~4); ~returnValue~1 = (string) ~laosEventArgs~4.ReturnValue; } return ~returnValue~1; }Wow!