using System; using System.Collections.Generic; public class DeadStoreOfLocal { delegate int D(); int fn(D d) { return d(); } public int M1() { int x = M2(); // BAD return (x = 1) + x; // GOOD } public int M2() { int x = 1; // GOOD return x + (x = 1); // BAD } public int M3() { return fn(() => { int y; y = 1; // GOOD return y; }); } public int M4() { return fn(delegate () { int y; y = 1; // GOOD: Assignment in delegate function return y; }); } public void M5() { int x = M3(); // BAD } public void M6() { int x = 42; x += 1; // BAD } public void M7() { int x = 42; x++; // BAD } public IEnumerable M8(IEnumerable source) { var count = 0; // GOOD foreach (var val in source) { yield return val; Console.WriteLine(++count); // GOOD } } public IEnumerable M9(IEnumerable source) { var count = 0; // GOOD foreach (var val in source) { count += 1; // GOOD yield return val; Console.WriteLine(count); } } public void M10(IEnumerable source) { foreach (var val in source) { // BAD } } } public abstract class ExceptionsFlow { public abstract void Process(); public void F() { string info1 = "", info2 = "", extra, message = ""; try { info1 = "Starting"; // GOOD: Used in exception handler message = "Unsuccessful completion"; // GOOD: Used in finally Process(); info2 = "Finishing"; // GOOD: Used in exception handler extra = "Dead store here"; // BAD: Dead store Process(); message = "Successful completion"; // GOOD: Used in finally info1 = "Used in handler"; // BAD: Used in handler, but not a reachable handler } catch (SystemException ex) { throw new Exception("Failure in " + info1, ex); } catch (Exception ex) { throw new Exception("Failure in " + info2, ex); } finally { Console.WriteLine(message); } } public void FinallyFlow1() { int stage = 0; try { Console.WriteLine("Stage " + stage); stage = 1; // GOOD: Used in finally throw new Exception(); } finally { Console.WriteLine("Stage " + stage); } } public void FinallyFlow2() { int stage = 0; try { Process(); } catch (Exception ex) // BAD { Console.WriteLine("Stage " + stage); stage = 3; // GOOD: Used in finally throw; } finally { Console.WriteLine("Stage " + stage); } } } public class OutParam { public void Test() { int x; Fn(out x); // BAD Fn(out _); // GOOD } void Fn(out int x) { x = 0; } } public class AssignmentArrayAliasing { public void Test(double[] x) { var y = x; // GOOD: y aliases an array that is accessed below y[0] %= 2; } } public class Captured { delegate int D(); int fn(D d) { return d(); } void M1() { var x = 1; // GOOD Action a = () => { Console.WriteLine(x); }; a(); } void M2() { var x = M6(); // BAD Action a = () => { x = 1; // GOOD Console.WriteLine(x); }; a(); } void M3() { int x; Action a = () => { x = 1; // BAD }; a(); } void M4() { int x; Action a = () => { x = 1; // GOOD Action aa = () => { Console.WriteLine(x); }; aa(); }; a(); } void M5() { int x = 0; // BAD: NOT DETECTED Action a = () => { x = 1; // GOOD }; a(); Console.WriteLine(x); } int M6() { fn(() => { int y = M6(); // BAD return (y = 1) + y; // GOOD }); int captured = 0; // GOOD: Variable captured variable fn(() => { return captured; }); return captured = 1; // BAD: NOT DETECTED } void M7() { var y = 12; // GOOD: Not a dead store (used in delegate) fn(() => { var x = y; // BAD: Dead store in lambda return 0; }); } Action A; void M8() { var cap = 0; // GOOD A = () => Console.WriteLine(cap); M9(); } void M9() { A(); } } class Patterns { void Test() { object o = null; if (o is int i1) { // GOOD Console.WriteLine($"int {i1}"); } else if (o is var v1) { // BAD } switch (o) { case "xyz": break; case int i2 when i2 > 0: // GOOD Console.WriteLine($"positive {i2}"); break; case int i3: // GOOD Console.WriteLine($"int {i3}"); break; case var v2: // BAD break; default: Console.WriteLine("Something else"); break; } } } class Tuples { void M() { (int x, (bool b, string s)) = GetTuple(); // GOOD Use(x); Use(b); Use(s); (x, (b, s)) = GetTuple(); // BAD: `b` Use(x); Use(s); (x, (_, s)) = GetTuple(); // GOOD Use(x); Use(s); } (int, (bool, string)) GetTuple() { return (0, (false, "")); } static void Use(T u) { } } class Initializers { string M1() { var s = string.Empty; // "GOOD" s = ""; return s; } string M2() { var s = ""; // "GOOD" s = ""; return s; } string M3() { string s = null; // "GOOD" s = ""; return s; } string M4() { var s = M3(); // BAD s = ""; return s; } string M5() { var s = default(string); // "GOOD" s = ""; return s; } string M6(bool b) { var s = ""; if (b) s = "abc"; // GOOD if (b) return s; return null; } string M7(bool b) { var s = ""; if (b) s = "abc"; // BAD if (!b) return s; return null; } } class Anonymous { int M(bool b) { var x = new { a = 0, b = 0 }; // GOOD if (b) { x = new { a = 1, b = 1 }; } else { x = new { a = 2, b = 2 }; } return x.a + x.b; } } class Finally { int M(bool b) { int i = 0; // GOOD try { if (b) throw new Exception(); } finally { i = 1; // GOOD } return i; } }