Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Tuesday, 29 May 2012
( JonSkeet | TekPub )
[TestFixture]
    public class DyanmicsTests
    {
        [Test]
        public void FirstDynamic()
        {
            //Jon likes Static stuff
            //string text = "hello";
            //object text = "hello";
            dynamic text = "hello";
            
            //System.Reflection - this is kind of what dynamic does?  dynamic a good fit here
            //PropertyInfo property = text.GetType().GetProperty("Length");
            //int length = (int) property.GetValue(text, null);

            //at execution time can't find Lengtht
            int length = text.Length;
            //there is type safety at execution time, just not compile time
            //eg Cannot implicitly convert type 'int' to 'string'
            //string length = text.Length;

            //compiler just figures out it is a string
            var text2 = "hello";

            //Stream stream = text.Foo as Stream;
            //var is a StreamWriter even though text is dynamic
            //var writer = new StreamWriter(text);

            //entirely statically typed
            Assert.AreEqual(5, length);

            //int result = CallMe(text);
            //Assert.AreEqual(2, result);

            //funky type inference at execution time
            dynamic ints = new List<int>();
            Type result = CallMe(ints);
            Assert.AreEqual(typeof(int), result);
        }
        public Type CallMe<T>(IEnumerable<T> sequence)
        {
            return typeof (T);
        }

        //public int CallMe(object x)
        //{
        //    return 1;
        //}

        //public int CallMe(string x)
        //{
        //    return 2;
        //}

        //deserializing some json
        //actually jon would use someone elses library!
        [Test]
        public void ExpandoTest()
        {
            //ExpandoObject expando = new ExpandoObject();
            dynamic expando = new ExpandoObject();
            IDictionary<string, object> dictionary = expando;

            dictionary["Name"] = "Jon";
            expando.Age = 35;
            //lambda expression
            Action greeting = () => Console.WriteLine("Hello");
            //expando.Greeting = (Action) (() => Console.WriteLine("Hello"));
            expando.Greeting = greeting;
            //prints to the console
            expando.Greeting();

            Func<int, int> doubler = x => x*2;
            expando.Doubler = doubler;
            int doubled = expando.Doubler(10);
            Assert.AreEqual(20, doubled);

            Assert.AreEqual("Jon", expando.Name);
            Assert.AreEqual(35, expando.Age);
        }

        [Test]
        public void SecondTest()
        {
            //this is quite nice, say if coming from a webrequest
            dynamic properties = GetProperties();
            string name = properties.Name;
            int age = properties.Age;
        }

        public dynamic GetProperties()
        {
            Dictionary<string, object> properties = new Dictionary<string, object>
                                                        {
                                                            {"Name", "Jon"},
                                                            {"Age", 35},
                                                            {"Town", "Reading"},
                                                            {"TimeZone", "Europe/London"}
                                                        };
            IDictionary<string,object> expando = new ExpandoObject();
            foreach (var pair in properties)
            {
                expando[pair.Key] = pair.Key;
            }

            return expando;
        }

        [Test]
        public void SqlTest()
        {
            dynamic sql = new DynamicSql();
            //named arguments
            dynamic results = sql.Books(author: "Jon Skeet", year: 2010);
            foreach (var result in results)
            {
                Console.WriteLine(result);
            }
        }
    }

    internal class DynamicSql : DynamicObject
    {
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            var callInfo = binder.CallInfo;
            StringBuilder builder = new StringBuilder("SELECT * FROM " + binder.Name + " WHERE ");
            for(int i = 0; i < callInfo.ArgumentCount; i++)
            {
                if (i != 0)
                {
                    builder.Append(" AND ");
                }
                builder.AppendFormat("{0} = @{0}", callInfo.ArgumentNames[i]);
            }
            Console.WriteLine("Woudl execute SQL: {0}", builder);
            for (int i = 0; i < callInfo.ArgumentCount; i++)
            {
                Console.WriteLine("Would set parameter {0} to {1}", callInfo.ArgumentNames[i], args[i]);
            }
            //returning an array of anonymous types
            result = new[] {new {Title = "C# in Depth"}};
            return true;
        }
    }
| | # 
( JonSkeet | TekPub )

Good stuff!

internal static class Extensions
    {
        internal static int DoubleLenth(this string text)
        {
            return text.Length * 2;
        }
    }

    [TestFixture]
    public class LinqTesting
    {
        [Test]
        public void Scrathpad()
        {
            // Disparate features of C#3 which come together in LINQ

            // Anonymous types and type inference
            var person = new { Name = "Jon", Age = 35 };

            // Lambda expressions
            // creating a delegate which says whether the input is more the 5 chars
            Func<string, bool> isLong = x => x.Length > 5;

            // Extension methods
            int doubleLength = "hello".DoubleLenth();

            // LINQ - a fairly consistent way of accessing data from multiple data
            // sources in as natural a way as possible.

            //**TEKPUB mastering linq series

            // Collection initializer
            List<string> names = new List<string>
                                     {
                                         "Rob, Friend",
                                         "Holly, Family",
                                         "This isn't a name",
                                         "Malcolm, Colleague",
                                         "Tom, Family"
                                     };
            // See if we can group each one of these names by relationship
            // and turn it into something more strongly typed.

            Regex pattern = new Regex("([^,]*), (.*)");

            //whole thing on right is a query expression
            //range variable called line
            var query = from line in names
                        let match = pattern.Match(line)
                        where match.Success
                        select new
                        {
                            Name = match.Groups[1].Value,
                            Relationship = match.Groups[2].Value
                        } into association
                        group association.Name by association.Relationship;
            
            // dot notation, method invokation syntax.. lambda syntax (hmm)
            //taking out the query expression..complex here.
            //this is what the compiler will make by magic behind the scenes
            //var query = names.Select(line => pattern.Match(line))
            //                  .Where()
            //                  .Select
            //                  .GroupBy

            //just outputs the correct lines
            //var query = from line in names
            //            let match = pattern.Match(line)
            //            where match.Success
            //            select line;

            foreach (var group in query)
            {
                Console.WriteLine("Relationship: {0}", group.Key);
                foreach (string name in group)
                {
                    Console.WriteLine("   {0}",name);        
                }
            }
        }

        [Test]
        public void asdf()
        {
            // Collection initializer
            List<string> names = new List<string>
                                     {
                                         "Rob, Friend",
                                         "Holly, Family",
                                         "This isn't a name",
                                         "Malcolm, Colleague",
                                         "Tom, Family"
                                     };

            //more noisy in query expression
            var query = from line in names
                        where line.Length < 15
                        select line;

            var query2 = names.Where(lines => lines.Length < 15);
        }

        [Test]
        public void JoinTest()
        {
            // Collection initializer
            List<string> names = new List<string>
                                     {
                                         "Rob, Friend",
                                         "Holly, Family",
                                         "This isn't a name",
                                         "Malcolm, Colleague",
                                         "Tom, Family"
                                     };

            List<int> lengths = new List<int> {10, 12, 13, 14, 15,16,17,18};

            //more noisy in query expression
            var query = from line in names
                        join length in lengths on line.Length equals length
                        where line.Length < 20
                        select line;
            foreach (string line in query)
            {
                Console.WriteLine(line);
            }
        }

        [Test]
        public void DataStuff()
        {
            var lines = from file in Directory.GetFiles("*.log")
                        from line in File.ReadLines(file)
                        where line.Contains("Error")
                        select line.Substring(10);
        }

        //edulinq.googlecode.com
    }
| | # 
# Monday, 28 May 2012
( JonSkeet | TekPub )

[TestFixture]
    public class AnonymousTypes
    {
        [Test]
        public void Demo()
        {
            //anonymous types are a C#3 feature
            //purely syntactic sugar..can use even if targeting .NET2
            //in C# is an immutable type with a bunch of properties

            //backtick a.. is the type when hover over
            var person = new { FirstName = "Jon", LastName = "Skeet" };
            var person2 = new { FirstName = "Jon", LastName = "Skeet" };
            //automatically overrides ToString to give { FirstName = Jon, LastName = Skeet }
            Console.WriteLine(person);

            var person3 = new
                              {
                                  FirstName = "Bob",
                                  LastName = "Jones",
                                  Address = new {Town = "Tilehurst", Country = "UK"}
                              };
            Console.WriteLine(person3); //{ FirstName = Bob, LastName = Jones, Address = { Town = Tilehurst, Country = UK } }

            //also overrides GetHashCode and AreEquals
            Assert.AreEqual(person, person2);
            //gives nice debugging ToString in unit test
            //Assert.AreEqual(person, person3);
            Assert.AreEqual(person.GetHashCode(), person2.GetHashCode());

            person = new {FirstName = "Dave", LastName = "Skeet"};
            //cant convert
            //person = new { LastName = "Skeet", FirstName="Bob"};

            //immutable this wont work
            //person.FirstName = "Alan";

            //makes property names of Length and LastName
            var person4 = new {person.FirstName.Length, person.LastName};

            var array = new string[10];
            //string[] array = {"asdf", "as"};
            //implicitly typed arrays
            var people = new[]
                             {
                                 person,
                                 new {FirstName = "Rob", LastName = "Conery"}
                             };
            var ints = new[] {1, 2, 3};
            //int[] ints = {1, 2, 3};
        }

        //generic method
        private void DoSomething<T>(T value)
        {
            Console.WriteLine(typeof(T));
        }

        [Test]
        public void GenericMethod()
        {
            var person = new {FirstName = "Jon", LastName = "Skeet"};
            //using type inference
            DoSomething(person);  //<>f__AnonymousType0`2[System.String,System.String]..seeing the unspeakable name with angle brackets in it.

        }
    }

| | # 
( JonSkeet | TekPub )

AS of .NET2 and .NET3.5.. better way of creating delegates

.NET2 – generics

public delegate void Int32Action(int value);

    //C#2 generics
    public delegate void GenericAction<T>(T value);

    [TestFixture]
    public class AnonymousFunctionsTest
    {
        private void MethodTakingString(string value)
        {
            Console.WriteLine(value);
        }

        [Test]
        public void MethodGroupConversion()
        {
            GenericAction<string> action = MethodTakingString;
            action("Hi");
        }

        private double SquareInt32(int x)
        {
            //return x*x;
            return Math.Sqrt(x);
        }

        [Test]
        public void ListConversion()
        {
            List<int> original = new List<int>() { 1, 2, 3 };
            //ConvertAll takes a delegate and applies it to each item in the list
            //List<int> squares = original.ConvertAll(SquareInt32);
            List<double> squareRoots = original.ConvertAll(SquareInt32);
            foreach (double value in squareRoots)
            {
                Console.WriteLine(value);
            }
        }

        [Test]
        public void AnonymousMethods()
        {
            //faff - need to make a whole method just when we want to write something to the console  
            Converter<int, double> converter = delegate(int x)
                                                   {
                                                       return Math.Sqrt(x);
                                                   };
            List<int> original = new List<int>() { 1, 2, 3 };
            List<double> squareRoots = original.ConvertAll(converter);
            foreach (double value in squareRoots)
            {
                Console.WriteLine(value);
            }
        }

        [Test]
        public void AnonymousMethods2()
        {
            List<int> original = new List<int>() { 1, 2, 3 };
            List<double> squareRoots = original.ConvertAll(delegate(int x)
                                {
                                    return Math.Sqrt(x);
                                });
            foreach (double value in squareRoots)
            {
                Console.WriteLine(value);
            }
        }

        [Test]
        //anonymous method showing that it can accept variable changes
        public void ClosureAnonymousMethods()
        {
            int calls = 0;
            double power = 0.5; //square root
            //a closure is some behaviour that can access the environment in which it is declared ie calls and power here
            //input, output
            Converter<int, double> converter = delegate(int x)
                                                   {
                                                       calls++;
                                                       //power is a captured variable
                                                       return Math.Pow(x, power);
                                                   };

            List<int> original = new List<int>() { 1, 2, 3 };
            List<double> squareRoots = original.ConvertAll(converter);
            foreach (double value in squareRoots)
            {
                Console.WriteLine(value);
            }
            Console.WriteLine("Total calls: {0}", calls);
            power = 2;
            List<double> squares = original.ConvertAll(converter);
            foreach (double value in squares)
            {
                Console.WriteLine(value);
            }
            Console.WriteLine("Total calls: {0}", calls);
        }

        [Test]
        //lambda expressions have pretty much taken over from anonymous methods as of C#3
        public void ClosureLambda()
        {
            double power = 0.5;
            //Converter<int, double> converter = delegate(int x)
            //this is now a lambda expression.. =>  goes to
            //Converter<int, double> converter = (int x) =>
            //using type inference to just declare parameter name
            //Converter<int, double> converter = (x) =>
            //when only have one, don't need brackets
            //Converter<int, double> converter = x =>
            //                                       {
            //                                           return Math.Pow(x, power);
            //                                       };

            //most people think of this as a lambda expressions..short and sweet..single expression on RHS
            //on LHS use type inference to work out types involved
            Converter<int, double> converter = x => Math.Pow(x, power);
            Console.WriteLine(converter); //prints something horrible!

            List<int> original = new List<int>() { 1, 2, 3 };
            List<double> squareRoots = original.ConvertAll(converter);
            foreach (double value in squareRoots)
            {
                Console.WriteLine(value);
            }
            power = 2;
            List<double> squares = original.ConvertAll(converter);
            foreach (double value in squares)
            {
                Console.WriteLine(value);
            }
        }

        [Test]
        //can build one from a lambda expression
        //it represents code as data
        //this is how linqtosql etc.. work
        public void ExpressionTrees()
        {
            //System.Linq.Expressions... ExpressionTree type which is a representation of some code
            Expression<Converter<int, double>> converter = x => Math.Pow(x, 0.5);
            //prints x => Pow(Convert(x), 0.5)
            //representing code as data
            Console.WriteLine(converter);

            //convert an expression tree into a delegate by compiling it
            Converter<int, double> compiled = converter.Compile();
            Console.WriteLine(compiled.Invoke(5));
        }

        [Test]
        public void IgnoreParameters()
        {
            //cant do this in lambdas.. but rare to have to do this
            Converter<int, double> converter = delegate { return 5.5; };
            Console.WriteLine(converter(10));
        }

        [Test]
        public void DangerWillRobinson()
        {
            //predefined delegate types
            //Action has a void return type
            Action<int> x1 = null;
            Action<int, string> x2 = null;
            Action<int, Guid, string> x3 = null;
            //returns an int
            Func<int> y = null;
            //Func is a delegate which returns something... takes int, returning double here
            Func<int, double> y1 = null;

            Func<int, double, string> y2 = Foo;

            string a = y2(2, 3d);
            Console.WriteLine("a is {0}", a);
        }

        public string Foo(int x, double y)
        {
            return x.ToString() + y.ToString();
        }

        [Test]
        public void DangerWillRobinson2()
        {
            List<string> words = new List<string>() { "Danger", "Will", "Robinson" };
            List<Action> actions = new List<Action>();
            foreach (string word in words)
            {
                //Action that doesn't take any paramaters and doesn't return anything
                //actions.Add(() => Console.WriteLine(word));
                string copy = word; //**Easy to get bitten by this using lambada expressios.. and this is the fix to use a local variable
                actions.Add(() => Console.WriteLine(copy));
            }

            //execute all the actions (delegates)
            foreach (Action action in actions)
            {
                action(); //prints Robinson Robinson robinson
            }
        }
| | # 
( JonSkeet | TekPub )

Delegates have been in .NET since 1.0.. have got a bit better with every version of C#

//a something that can do something with an integer!

Delegate here are a bit like single method interfaces..they encapsulate a bit of behaviour

//delegate type
    //behind the scenes compiler creates a class which inherits from System.MulticastDelegate
    public delegate void Int32Action(int value);

    //similar to:
    public interface IInt32Action
    {
        void DoIt(int value);
    }

    public class Delegates : IInt32Action
    {
        private readonly string name;

        public Delegates(string name)
        {
            this.name = name;
        }

        public Delegates(): this("unknown")
        {
        }

        public void DoIt(int value)
        {
            Console.WriteLine("Interface implementation: {0}", value);
        }

        public void RandomRob(int value)
        {
            Console.WriteLine("{0} Delegate implementation: {1}", name, value);
        }

        //static means related to the type, and not any particular instance of the type
        public static void StaticRob(int value)
        {
            Console.WriteLine("Static method: {0}", value);
        }

        public static void StaticRob2(int value)
        {
            Console.WriteLine("Static method: {0}", value);
        }
    }
[TestFixture]
public class DelegatesTest
{
    [Test]
    public void SingleMethodInterface()
    {
        //a something that can do something with an integer!
        IInt32Action action = new Delegates();
        action.DoIt(10);
    }

    [Test]
    public void SimpleDelegateFromMethod()
    {
        //delegates have a target
        Delegates target = new Delegates("Jon");
        //wiring an instance method up to a delegate, then invoking
        //C#1 way of writing ie new Int32Action
        //encapsulating - something we can invoke with an integer
        //can think of this as a method we are passing around
        Int32Action action = new Int32Action(target.RandomRob);

        action.Invoke(5);
        //same as Invoke above
        action(6);
    }

    [Test]
    public void DelegateFromStaticMethod()
    {
        Int32Action action = new Int32Action(Delegates.StaticRob);
        action.Invoke(7);
    }

    [Test]
    public void MultiCast()
    {
        Int32Action action1 = new Int32Action(Delegates.StaticRob);
        Int32Action action2 = new Int32Action(Delegates.StaticRob2);

        //single delegate instance that refers to 2 individual actions
        Int32Action action3 = action1 + action2;
        action3(20);
    }

    //all C#1 so far

Events

Events use delegates.

Observer pattern – got something that happens… when something happens, I want to react.

ie when user clicks on button, I want something to happen

public delegate void FakeEventHandler(string reason);
    
    public class FakeEventRaiser
    {
        private FakeEventHandler currentHandler = null;

        public void AddHandler(FakeEventHandler handler)
        {
            currentHandler = currentHandler + handler;
        }

        public void RemoveHandler(FakeEventHandler handler)
        {
            currentHandler = currentHandler - handler;
        }

        public void DoSomething(string text)
        {
            FakeEventHandler tmp = currentHandler;
            if (tmp != null)
            {
                tmp.Invoke(text);
            }
        }
    }
[TestFixture]
    public class FakeEventRaiserTests
    {
        private void ReportToConsole(string text)
        {
            Console.WriteLine("Called: {0}", text);    
        }

        [Test]
        public void RaiseEvents()
        {
            //FakeEventHandler handler = new FakeEventHandler(ReportToConsole);
            //implicit method group conversions
            FakeEventHandler handler = ReportToConsole;

            FakeEventRaiser raiser = new FakeEventRaiser();
            raiser.DoSomething("Not subscribed");

            raiser.AddHandler(handler);
            raiser.DoSomething("Subscribed");

            raiser.AddHandler(handler);
            raiser.DoSomething("Subscribed twice");

            raiser.RemoveHandler(handler);
            raiser.RemoveHandler(handler);
            raiser.DoSomething("Unsubscribed");
        }
    }

asdf

public delegate void ClickHandler(object sender, EventArgs e);

    public class LonghandEventRaiser
    {
        private ClickHandler currentHandler = null;

        //private void AddHandler(ClickHandler handler)
        //{
        //    currentHandler = currentHandler + handler;
        //}

        //private void RemoveHandler(ClickHandler handler)
        //{
        //    currentHandler = currentHandler - handler;
        //}

        public void OnClick()
        {
            ClickHandler tmp = currentHandler;
            if (tmp != null)
            {
                tmp.Invoke(this, EventArgs.Empty);
            }
        }

        //longhand
        //public event ClickHandler Click
        //{
        //    add { AddHandler(value); }
        //    remove { RemoveHandler(value); }
        //}

        public event ClickHandler Click
        {
            add { currentHandler += value; }
            remove {currentHandler -= value;}
        }
    }
[TestFixture]
    public class LonghandeEventRaiserTests
    {
        private void ReportToConsole(object sender, EventArgs e)
        {
            Console.WriteLine("Report to console was called");    
        }

        [Test]
        public void RaiseEvents()
        {
            ClickHandler handler = ReportToConsole;

            var raiser = new LonghandEventRaiser();
            raiser.OnClick();

            raiser.Click += handler;
            raiser.OnClick();

            raiser.Click += handler;
            raiser.OnClick();

            raiser.Click -= handler;
            raiser.Click -= handler;
            raiser.OnClick();
        }
    }

asdf

public class ShorthandEventRaiser
    {
        public void OnClick()
        {
            //interestinglly this Click is referring to the field
            ClickHandler tmp = Click;
            if (tmp != null)
            {
                tmp.Invoke(this, EventArgs.Empty);
            }
        }

        //field like event - compiler generates
        public event ClickHandler Click;

        //auto implemented property..
        //compiler generates backing field
        //and property accessor code
        public string Name { get; set; }
        
        //looks like a property
        //public event ClickHandler Click
        //{
        //    add { currentHandler += value; }
        //    remove { currentHandler -= value; }
        //}
    }
[TestFixture]
    public class ShorthandeEventRaiserTests
    {
        private void ReportToConsole(object sender, EventArgs e)
        {
            Console.WriteLine("Report to console was called");    
        }

        [Test]
        public void RaiseEvents()
        {
            ClickHandler handler = ReportToConsole;

            var raiser = new ShorthandEventRaiser();
            raiser.OnClick();

            raiser.Click += handler;
            raiser.OnClick();

            raiser.Click += handler;
            raiser.OnClick();

            raiser.Click -= handler;
            raiser.Click -= handler;
            raiser.OnClick();
        }
    }
| | # 
( JonSkeet | TekPub )
public class GenericCollectionTests
{
    //2 types of generics
    //generic types - only look at these today
    //generic methods

    [Test]
    public void ListBasics()
    {
        List<string> names = new List<string>();
        names.Add("fred");
        Assert.AreEqual("fred", names[0]);
    }

    [Test]
    public void Generics()
    {
        //string is the generic type argument.. hi is the argument
        Fred<string> fred = new Fred<string>("hi");
        Assert.AreEqual("hi", fred.Foo());
        
        //var only used to declare local variables
        var fred2 = new Fred<int>(100);
        Assert.AreEqual(100, fred2.Foo());
    }

    [Test]
    public void DictionaryNastyness()
    {
        Dictionary<string, List<int>> map = new Dictionary<string, List<int>>();
        //much more readable
        var map2 = new Dictionary<string, List<int>>();
    }
}

//T is a generic type parameter
public class Fred<T>
{
    //field
    //string could be decimal.. all still compiles..
    //so can make it generic.. don't care what the type is
    private readonly T greeting;

    //greeting is the parameter
    public Fred(T greeting)
    {
        this.greeting = greeting;
    }

    public T Foo()
    {
        return greeting;
    }
}

public class FredOld
{
    //field
    //string could be decimal.. all still compiles..
    //so can make it generic.. don't care what the type is
    private readonly string greeting;

    public FredOld(string greeting)
    {
        this.greeting = greeting;
    }

    public string Foo()
    {
        return greeting;
    }
}
| | # 
( JonSkeet | TekPub )
[Test]
        public void ArrayTest()
        {
            //integer array of size 10.. 10 integers - can't change size once created
            //int is a value type, but as soon as its an array.. reference type
            int[] array = new int[10];

            int array1 = 0;
            int array2 = 0;
            int array3 = 0;
            //...in an array, the values can accessed as variables

            //all arrays are reference types
            //have changed the reference to a new array here
            array = new int[50];

            //initialized with null values
            string[] strings = new string[10];
        }

        [Test]
        public void ArrayTest2()
        {
            int[] array = new int[5];
            array[0] = 20;
            array[1] = 30;
            int value = array[0];
            Assert.AreEqual(20, value);
            Assert.AreEqual(5, array.Length);
            for (int i = 0; i < array.Length; i++)
            {
                //Console.WriteLine(array[i]);
            }
            //compiler would actually do a for loop like above
            foreach (int tmp in array)
            {
                Console.WriteLine(tmp);
            }

            //doing a foreach.. compiler would Enumerate
            //can do this assignment as array implements IEnumerable
            IEnumerable<int> sequence = array;
        }

        //initialize array very simply by giving it values
        public static readonly int[] Seeds = {10, 20, 30};

        [Test]
        public void ArrayMutable()
        {
            Seeds[0] = 100;
            //Assert.AreEqual(10, Seeds[0]); //always fails!  can't have an immutable array
            //All other collections build on Array
            //Unless want cracking performance, use greater level of abstraction ie more generic collections
        }
| | # 
( JonSkeet | TekPub )
public class GenericListAndDictionaries
{
    [Test]
    //a list is a sequence.. which keeps its order
    public void ListBasics()
    {
        //list of T, and we're using string as the type argument
        List<string> names = new List<string>();
        names.Add("fred");
        Assert.AreEqual("fred", names[0]);
        Assert.AreEqual(1, names.Count);
        names.Add("betty");
        Assert.AreEqual(2, names.Count);

        names.RemoveAt(0);
        Assert.AreEqual(1, names.Count);
        Assert.AreEqual("betty", names[0]);

        //Jon tends not to use List.Sort or Array.Sort as he uses linq instead

        foreach (string x in names)
        {
            Console.WriteLine(x);
        }

        //behind the scenes.. the list actually has an array in it
        //array is only partially used
        //when adding to a list.. it asks, do I have any spare capacity,.. if yes, put into the array... and increase internal counter for number elements used
        //if not enough room, create new array, copy everything into it

        //note havent passed anything to constructor or called it.. equivalent to ()
        var integers = new List<int> {1, 2, 3};
        //equivalent to:
        var tmp = new List<int>();
        tmp.Add(1);
        tmp.Add(2);
        tmp.Add(3);

        //a lot of list methods are superceeded now by linq
    }

    [Test]
    //myDictionary[key]= value
    //basically a way of looking something up really quickly
    //very efficient..uses a hashtable..basically a way of mapping any key to a number
    public void DictionaryBasics()
    {
        var map = new Dictionary<string, int>();
        map.Add("foo",10);
        //an indexer
        map["bar"] = 20;

        foreach (var entry in map)
        {
            Console.WriteLine("{0} {1}", entry.Key, entry.Value);
        }

        //common - fetching a value by its key
        int value = map["foo"];
        Assert.AreEqual(10, value);

        //however if key doesnt exist above method will throw an exception
        int value2;
        //out passes a value by reference and shouldn't be used under normal circumstances
        bool keyFound = map.TryGetValue("blah", out value2);
        Assert.IsFalse(keyFound);
        Assert.AreEqual(0,value2);

        keyFound = map.TryGetValue("bar", out value2);
        Assert.IsTrue(keyFound);
        Assert.AreEqual(20,value2);

        Assert.AreEqual(2, map.Count);

        map = new Dictionary<string, int>
                  {
                      {"foo", 50},
                      {"bar", 70}
                  };
    }
| | # 
( JonSkeet | TekPub )
public class BaseClass
    {
        //field
        private readonly string name;
        //property
        public string Name { get { return name; } }
        
        //constructor chaining.. initializers to call each other in succession
        public BaseClass() : this("default")
        {
        }

        public BaseClass(string name)
        {
            this.name = name;
        }

        //virtual means I can override it in my derived class
        public virtual int CalculateResult(int x)
        {
            return x*2;
        }

        public int TrebleInput(int x)
        {
            return x*3;
        }
    }
//in java superclass and subclass
    //in c# it is base class and derived class
    //: inherits from, or derives from
    public class DerivedClass : BaseClass
    {
        //parameterless constructor
        public DerivedClass() : base("Derived default")
        {
        }
            
        public DerivedClass(string localName) : base("Derived " + localName)
        {
        }

        public override int CalculateResult(int x)
        {
            return x / 2;
        }

        public int QuadrupleInt(int x)
        {
            return x*4;
        }
    }
[TestFixture]
public class BaseClassTests
{
    [Test]
    public void CalculateResultDoublesInput()
    {
        BaseClass test = new BaseClass();
        Assert.AreEqual(16, test.CalculateResult(8));
    }
    
    [Test]
    public void TrebleResultTreblesInput()
    {
        BaseClass test = new BaseClass();
        Assert.AreEqual(15, test.TrebleInput(5));
    }

    [Test]
    public void NameDefaultsToDefault()
    {
        BaseClass test = new BaseClass();
        Assert.AreEqual("default", test.Name);
    }
    
    [Test]
    public void SpecifiedNameIsPropogated()
    {
        BaseClass test = new BaseClass("Jon");
        Assert.AreEqual("Jon", test.Name);
    }
}
[TestFixture]
    public class DerivedClassTests
    {
        [Test]
        public void DefaultName()
        {
            //assigning the reference of new DerivedClass, to a variable of type BaseClass
            //compile time type is baseclass, execution time type is derived class
            BaseClass test = new DerivedClass();
            Assert.AreEqual("Derived default", test.Name);
        }

        [Test]
        public void GivenName()
        {
            BaseClass test = new DerivedClass("Dave");
            Assert.AreEqual("Derived Dave", test.Name);
        }

        [Test]
        public void QuadrupleInput()
        {
            //compile time type is DerivedClass
            DerivedClass test = new DerivedClass();
            Assert.AreEqual(16, test.QuadrupleInt(4));
        }

        [Test]
        public void TrebleResultTreblesInput()
        {
            BaseClass test = new DerivedClass();
            Assert.AreEqual(15, test.TrebleInput(5));
        }

        [Test]
        public void CalculateResultHalvesInput()
        {
            BaseClass test = new DerivedClass();
            Assert.AreEqual(20, test.CalculateResult(40));
        }

        //streams - eg file, http, memory, xml
    }
public abstract class Dancer
{
    //readonly fields have to be assigned in the constructor
    private readonly string name;

    public string Name { get { return name; } }

    //doesn't really need to be protected as can't instantiate directly on abstract class
    protected Dancer(string name)
    {
        this.name = name;
    }

    public abstract void Dance();

    //a concrete method
    public void DanceTwice()
    {
        Dance();
        Dance();
    }
}
public class TapDancer : Dancer
    {
        public TapDancer() : base("My tap dancer") {}

        public override void Dance()
        {
            Console.WriteLine("drip drip");       
        }
    }
[TestFixture]
    public class TapDancerTests
    {
        [Test]
        public void DancerName()
        {
            Dancer dancer = new TapDancer();
            Assert.AreEqual("My tap dancer", dancer.Name);
        }

        [Test]
        public void DanceBabyDance()
        {
            Dancer dancer = new TapDancer();
            dancer.Dance();
        }

        [Test]
        public void DanceTwice()
        {
            Dancer dancer = new TapDancer();
            dancer.DanceTwice();
        }
    }
| | # 
( JonSkeet | TekPub )

//sealed class you can't derive from
    public sealed class Chainsaw : IControllable
    {
        public void Start()
        {
            Console.WriteLine("Brrrrrm");
        }

        public void Stop()
        {
            Console.WriteLine("da da da da");
        }
    }
//a contract
    //typically interfaces define an ability
    //ending an interface name with able is usually a good idea
    public interface IControllable
    {
        //members
        void Start();
        void Stop();
    }
public class TapDancer : Dancer
    {
        public TapDancer() : base("My tap dancer") {}

        public override void Dance()
        {
            Console.WriteLine("drip drip");       
        }
    }

//abstract class you have to derive from for it to be useful
    public abstract class Dancer : IControllable
    {
        //readonly fields have to be assigned in the constructor
        private readonly string name;

        public string Name { get { return name; } }

        //doesn't really need to be protected as can't instantiate directly on abstract class
        protected Dancer(string name)
        {
            this.name = name;
        }

        public abstract void Dance();

        public void Start()
        {
            Console.WriteLine("Started dancing");
            Dance();
        }
         
        public void Stop()
        {
            Console.WriteLine("Stopped dancing");
        }

        //a concrete method
        public void DanceTwice()
        {
            Dance();
            Dance();
        }
    }

public class StartAndStopper
    {
        public void StartAndStop(IControllable controllable)
        {
            controllable.Start();
            controllable.Stop();
        }
    }
[TestFixture]
    public class StartAndStopperTests
    {
        [Test]
        public void StartAndStopTest()
        {
            Dancer dancer = new TapDancer();
            Chainsaw chainsaw = new Chainsaw();

            StartAndStopper test = new StartAndStopper();
            test.StartAndStop(dancer);
            test.StartAndStop(chainsaw);
        }
    }

IDisposable.Dispose – implemented by all sorts of things..  UI controls, filestreams, dbconnections

IEnumerator<T> implements

IEnumerable<T>..oneof the most useful interfaces in .NET

 

Composition

IAuthenticator (or able)… single method Authenticate..takes.

if we have only 1 method of authentication.. could just make an authenticate class.. but..lose flexibility..testing!…this is a service.

**DO THIS**

eg we could pass in our own authenticator : IAuthenticator.. which say if username and password are the same, then it is authenticated.

eg if can express dependencies in abstraction form…eg if want to test that a full disk gives as IO error when doing a write, could pass in a .. something.

[TestFixture]
    //both array and list<T> work as they implement IEnumerable
    public class ForEachTests
    {
        [Test]
        public void ArrayIteration()
        {
            int[] array = new int[] {3, 5, 10};
            DisplayContents(array);
        }

        [Test]
        public void ListIteration()
        {
            List<string> list = new List<string> {"a","b","c"};
            DisplayContents(list);
        }

        //Gereric method, so it has its own type parameter of T
        //faking up foreach compiler gives us.
        private void DisplayContents<T>(IEnumerable<T> collection)
        {
            //this will call IDisposable in a try finally block
            using (IEnumerator<T> iterator = collection.GetEnumerator())
            {
                while (iterator.MoveNext())
                {
                    Console.WriteLine(iterator.Current);
                }
            }
        }
    }
| | # 
# Sunday, 27 May 2012
( JonSkeet | TekPub )

Conditionals like if and else etc..

[Test]
public void ReturnTest()
{
    Console.WriteLine("Hello");
    return;
    Console.WriteLine("After return"); //unreachable code detected warning
}

[Test]
public int MethodReturningInt32() //a friendly name for the alias int...which is actually an Int32
{
    byte x = 10;
    return x; //implicit conversion to int
}

[Test]
public void IfElse()
{
    int x = 10;
    if (x > 5)
    {
        Console.WriteLine("x is greater than 5");
    }
    if (x < 5)
    {
        Console.WriteLine("x is less than 5");
    }
    else
    {
        Console.WriteLine("is greater than 5");
    }

    //if (x) //wont compile ie if x isn't null
    if (x != 0)
    {
    }
    bool y = false;
    if (!y)
    {
    }
}

[Test]
public void WhileTests()
{
    int x = 10;
    while (x < 15)
    {
        Console.WriteLine(x);
        x++;
    }
    Console.WriteLine("Final value of x {0}", x);
    Assert.AreEqual(15, x);
}

[Test]
public void DoWhileTests()
{
    //jon hardly ever uses..always runs once (set x to 20 and it will end up as 21)
    int x = 10;
    do
    {
        Console.WriteLine(x);
        x++;
    } while (x < 15);
    Console.WriteLine("Final value of x: {0}", x);
    Assert.AreEqual(15, x);
}

[Test]
public void BreakInWhile()
{
    int x = 10;
    while (x < 15)
    {
        if (x % 3 == 0) //multiple of 3
        {
            break; //break out of nearest enclosing loop ie the while
        }
        Console.WriteLine(x);
        x++;
    }
    Assert.AreEqual(12, x);
}

[Test]
public void ContinueInWhile()
{
    int x = 10;
    while (x < 15)
    {
        if (x % 3 == 0) //multiple of 3
        {
            x += 2;
            continue; //skipping the x++
        }
        x++;
    }
    Assert.AreEqual(15, x);
}

[Test]
public void ForLoops()
{
    //for(initialization; condition; action ;)
    //action happens at end brace
    for (int x = 0, y = 0; x + y < 10; x++, y += 2)
    {
        Console.WriteLine("{0} {1}", x, y);
    }
}

[Test]
public void BreakingInWhile()
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            Console.WriteLine("{0} {1}", i, j);
            if (i + j == 4)
            {
                break; //only will break out to end of j loop... so will always get i going from 0 to 3
            }
        }
    }
}

[Test]
public void ForEachTests()
{
    string[] strings = { "Jon", "Holly", "Tom", "Robin", "William" };
    /*for (int i = 0; i < strings.Length; i++)
    {
        Console.WriteLine(strings[i]);
    }*/
    foreach (string value in strings)
    {
        Console.WriteLine(value);
        //value = "asfd"; readonly!
    }
}

[Test]
public void ForEachOverList()
{
    //generic list.. a collection of strings
    List<string> strings = new List<string>() { "Jon", "Holly", "Tom", "Robin", "William" };
    //foreach (string value in strings)
    //{
    //    Console.WriteLine(value);
    //}

    //list of string implements IEnumerable of string
    //here is a translation as to what the compiler is doing under the hood
    { //braces here to enclose scope
        string value;
        using (IEnumerator<string> iterator = strings.GetEnumerator())
        {
            while (iterator.MoveNext())
            {
                value = iterator.Current;
                Console.WriteLine(value);
            }
        }
    }
}
| | # 
( JonSkeet | TekPub )
[Test]
        public void TimeSpanUsage()
        {
            // System.DateTime (.NET 1.0)
            // System.TimeSpan (.NET 1.0)
            // System.DateTimeOffset (.NET 2.0SP1 / .NET 3.5)
            // System.TimeZoneInfo (.NET 3.5)
            // System.Timezone - rubbish.

            // A timespan is a number of ticks.. where a tick is 10ns
            // eg 2secs is a fixed amount of time
            // whereas a month is not a fixed amount of time

            TimeSpan fiveSeconds = TimeSpan.FromSeconds(5);
            TimeSpan halfAMinute = TimeSpan.FromMinutes(.5); //a double.. floating point..
            Assert.AreEqual(TimeSpan.FromMilliseconds(35000), fiveSeconds + halfAMinute); //timespan overloads + operator so can do this
            //Assert.AreEqual(5000, fiveSeconds.Milliseconds); //gets the milliseconds component
            Assert.AreEqual(5000d, fiveSeconds.TotalMilliseconds); //gets the milliseconds component
            Assert.AreEqual(0.5d, halfAMinute.TotalMinutes);
        }

        [Test]
        public void DateTimeUsage()
        {
            // More widely used today than should be..
            // Saying that this time is a local one.
            DateTime jonsTime = new DateTime(2011,4,1,21,24,0, DateTimeKind.Local); //April 1st 2011..but he is on  BST (British Summer Time)
            DateTime robsTime = new DateTime(2011,4,1,10,24,0, DateTimeKind.Local);
            DateTime davesTime = new DateTime(2011,4,1,15,24,0, DateTimeKind.Local); //As I'm in UTC-6 currently (Indiana)
            
            //DateTime unspecifiedNine = new DateTime(2011,4,1,15,24,0, DateTimeKind.Unspecified); //hangover from .NET1.1..convert each way.
            
            DateTime utcTime = new DateTime(2011,4,1,20,24,0, DateTimeKind.Utc); // GMT and UTC roughly the same thing..

            //no way of saying robsTime and jonsTime represent the same instant
            Assert.AreEqual(utcTime, davesTime.ToUniversalTime()); // Assuming the systems default timezone (Indiana)
            Assert.AreEqual(utcTime, utcTime.ToUniversalTime()); // Said UTC already so wont convert anymore

            Assert.AreEqual(davesTime, davesTime.ToLocalTime());
            Assert.AreEqual(davesTime, utcTime.ToLocalTime());
            
            //Assert.AreEqual(utcTime, unspecified.ToUniversalTime());

            //DateTime and TimeSpan are both value types - structs... immutable
            DateTime bedTime = jonsTime + TimeSpan.FromHours(2);
            Assert.AreEqual(new DateTime(2011,4,1,23,24,0, DateTimeKind.Local), bedTime);

            //Daylight savings not working
            DateTime beforeTranstion = new DateTime(2011,3,27,0,0,0);
            DateTime afterTranstion = new DateTime(2011,3,27,3,0,0);
            Assert.AreEqual(TimeSpan.FromHours(3), afterTranstion - beforeTranstion); //as far as jon was concerned.. only 2 hours had passed

            //do it in UTC is much easier..actually wont work on my machine as daylight savings happens at different date in the US.
            DateTime beforeTranstionUtc = beforeTranstion.ToUniversalTime();
            DateTime afterTranstionUtc = afterTranstion.ToUniversalTime();
            //Assert.AreEqual(TimeSpan.FromHours(2), afterTranstionUtc - beforeTranstionUtc); //as far as jon was concerned.. only 2 hours had passed
        }

        [Test]
        //another struct
        public void DateTimeOffsetTests()
        {
            // .NET2.0SP1 / .NET3.5
            DateTimeOffset jonsTime = new DateTimeOffset(2011,4,1,21,24,0,TimeSpan.FromHours(1)); //UTC+1
            Console.WriteLine(jonsTime);
            Console.WriteLine(jonsTime.ToUniversalTime());

            DateTimeOffset robsTime = new DateTimeOffset(2011,4,1,10,24,0,TimeSpan.FromHours(-10));
            Assert.AreEqual(jonsTime, robsTime);
            Assert.AreEqual(jonsTime.ToUniversalTime(), robsTime.ToUniversalTime()); //important one
        }

        [Test]
        public void TimeZoneInfoTests()
        {
            // .NET3.5
            // history..Argentina changed with 2 weeks notice not to change to daylight savings
            TimeZoneInfo zone = TimeZoneInfo.Local;
            //TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
            //Assert.AreEqual(TimeSpan.FromHours(0), zone.GetUtcOffset(new DateTime(2011,3,27,0,0,0))); //fails because I'm in CST
            Console.WriteLine("{0} {1} {2}", zone.Id, zone.DisplayName, zone.DaylightName);
        }

        //other months other than gregorian ie different cultures with 13 months..

        //DateTime.. cant have just a date
        //TimeSpan can give you time only...
| | # 
# Saturday, 26 May 2012
( TekPub )
[TestFixture]
    public class StringEncodingTests
    {
        private static Encoding enc8 = Encoding.UTF8;

        [Test]
        public void StringTests()
        {
            //encoding easier.. cultures hard
            //a string is a set of UTF16 code units... Unicode is how characters are represented
            //ie maps a character to a number.. then an encoding maps numbers to bytes.
            //string AB = "AB"; // A = Unicode 65, and B = Unicode 66.  4 Bytes.. 16bit Integer.

            //range of char: 0-65535
            //kilngon is in unicode?
            string text = "Cafe/";
            Assert.AreEqual("/efaC", Reverse(text));
        }

        private static string Reverse(string text)
        {
            char[] chars = text.ToCharArray();
            Array.Reverse(chars);
            return new string(chars);
        }

        [Test]
        public void EncodingTest()
        {
            //Encoding encoding = new UTF8Encoding();
            Encoding encoding = Encoding.UTF8;
            //Encoding encoding = new UnicodeEncoding();
            //UTF16
            string text = "ABC";
            byte[] binary = encoding.GetBytes(text);
            Assert.AreEqual(65, binary[0]);
            Assert.AreEqual(66, binary[1]);
            Assert.AreEqual(67, binary[2]);
        }

        //encoding.. a way of converting from text to binary data, and back again
        //static Encoding enc8 = Encoding.UTF8;

        [Test]
        public void Crypto()
        {
            //hashing
            //sha256 is better then md5
            using (var md5 = MD5.Create())
            {
                byte[] hash = md5.ComputeHash(new byte[10]);
                //string hashAsText = Encoding.UTF8.GetString(hash);
                //string hashAsText = new UTF8Encoding().GetString(hash); //converting to text this way wont work well

                string hashAsText = Convert.ToBase64String(hash); //good
                byte[] backAgain = Convert.FromBase64String(hashAsText);
                Console.WriteLine(hashAsText);
            }
        }

        [Test]
        public void NastyGotcha()
        {
            File.WriteAllText("file.txt", "Hello world"); //will default to UTF8
            File.WriteAllText("file.txt", "Hello world", Encoding.Default); //ahh this will be the machine default.
        }
| | # 
( JonSkeet | regex | TekPub )
[Test]
public void RegexTest1()
{
    // When worth using regex? Or use more primitive
    // If you have a complex pattern.. have to use many primitive operations

    Regex pattern = new Regex(" ");
    string text = "Jon Skeet";
    string[] words = pattern.Split(text);
    Assert.AreEqual("Jon", words[0]);
    Assert.AreEqual("Skeet", words[1]);
}

[Test]
public void RegexTest2()
{
    Regex pattern = new Regex(@"\d");//digit..verbatim string literal
    string text = "Jon0Skeet1Rob2Conery";
    string[] words = pattern.Split(text);
    Assert.AreEqual("Jon", words[0]);
    Assert.AreEqual("Skeet", words[1]);
    Assert.AreEqual("Rob", words[2]);
    Assert.AreEqual("Conery", words[3]);
}

[Test]
// Using regex to parse a log file
// ie using regex to pattern match
public void RegexTest3()
{
    Regex pattern = new Regex(@"\d");//digit..verbatim string literal
    string text = "Jon0Skeet1Rob2Conery";
    string[] words = pattern.Split(text);
    Assert.AreEqual("Jon", words[0]);
    Assert.AreEqual("Skeet", words[1]);
    Assert.AreEqual("Rob", words[2]);
    Assert.AreEqual("Conery", words[3]);
}

[Test]
public void PatternMatchLogFileParser()
{
    string sampleLine = "WARNING 05/10/2011 13:15:15.000 ---FooBar--- The foo has been barred";

    //john finds this hard!  MSDN regex is good
    Regex pattern = new Regex(@"(?<level>\S+) " + //brackets is grouping.. and name.  \S is non space chars   + means 1 or more  space
                              @"(?<timestamp>\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}\.\d{3}) " + // \d digit exactly 2 of them then forwardslash then 2 digits forwardslash then 4 digits escape the dot which is anything
                              @"---(?<category>[^-]+)--- " + //not a hypen in category.. carot is anything except
                              @"(?<message>.*)");//dot is anything, star is 0 or more times

    Match match = pattern.Match(sampleLine);//Matches tries to match the pattern multiple times
    if (match.Success)
    {
        string level = match.Groups["level"].Value;
        Console.WriteLine(level);
        string timestamp = match.Groups["timestamp"].Value;
        DateTime dateTime = DateTime.ParseExact(timestamp, "dd/MM/yyyy HH:mm:ss.fff", CultureInfo.InvariantCulture);
        DateTime date = dateTime.Date;
        Console.WriteLine(date);
        Console.WriteLine(match.Groups["category"]);
        Console.WriteLine(match.Groups["message"]);
    }
}

[Test]
public void TakeOutAllTheVowels()
{
    string sampleLine = "Hello, world";
    Regex pattern = new Regex("[aeiou]");
    string noVowels = pattern.Replace(sampleLine, "?");
    Assert.AreEqual("H?ll?, w?rld", noVowels);
}

[Test]
public void TakeOutAllTheVowels2()
{
    string sampleLine = "Hello, world";
    //Regex pattern = new Regex("[aeiou]"); //simpler here!
    //string noVowels = pattern.Replace(sampleLine, "?");
    string noVowelHardWay = sampleLine.Replace('a', '?') //character literal
                                        .Replace("e", "?") //method chaining
                                        .Replace("i", "?")
                                        .Replace("o", "?")
                                        .Replace("u", "?");
    Assert.AreEqual("H?ll?, w?rld", noVowels);
}
| | # 
( JonSkeet | TekPub )
[TestFixture]
    public class StringStuffMore
    {
        [Test]
        public void FindThings()
        {
            string x = "hello";
            int firstEllIndex = x.IndexOf('l');
            Assert.AreEqual(2, firstEllIndex);
            int secondEllIndex = x.IndexOf('l', firstEllIndex + 1);
            Assert.AreEqual(3, secondEllIndex);
            int thirdEllIndex = x.IndexOf('l', secondEllIndex + 1);
            Assert.AreEqual(-1, thirdEllIndex);
        }

        [Test]
        public void FindMoreThings()
        {
            string x = "hello";
            int firstEllIndex = x.IndexOf("ll");
            Assert.AreEqual(2, firstEllIndex);
            int secondEllIndex = x.IndexOf("ll", firstEllIndex + 1);
            Assert.AreEqual(-1, secondEllIndex);
        }

        [Test]
        public void FindMoreThings2()
        {
            string x = "jon skeet";
            int spaceIndex = x.IndexOf(' ');
            if (spaceIndex != -1)
            {
                string first = x.Substring(0, spaceIndex);
                string last = x.Substring(spaceIndex + 1); //starts 1 after the space
                Assert.AreEqual("jon", first);
                Assert.AreEqual("skeet", last);
            }
        }

        [Test]
        public void Split()
        {
            string x = "Jon Skeet-Webb";
            //equivalednt to x.Split(new char[] { ' ', '-','|'});
            //syntactic sugar params array
            //string[] words = x.Split(' ', '-', '|'); //splitting on multiple delimeters
            string[] words = x.Split(new char[] {' ', '-', '|'}, 2); //gives 2 back

            foreach (string word in words)
            {
                Console.WriteLine(word);
            }

            Assert.AreEqual("Jon", words[0]);
            Assert.AreEqual("Skeet-Webb", words[1]);
        }

        [Test]
        public void Csv()
        {
            string x = "0,1,,3,,5,,7";
            //string[] words = x.Split(',');
            string[] words = x.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < words.Length; i++)
            {
                Console.WriteLine("{0}: {1}", i, words[i]);
            }
            Assert.AreEqual(5, words.Length);// No null entries in the CSV
        }
| | # 
# Friday, 25 May 2012
( JonSkeet | TekPub )
[TestFixture]
    public class StringTest
    {
        [Test]
        public void Length()
        {
            string x = "hello"; //string is an alias to System.String
            //String y = "hello"; //System.String

            //string is a sequence of unicode characters
            
            Assert.AreEqual(5,x.Length);

            //char is a single character
        }

        [Test]
        public void NullTermination()
        {
            char[] nullTerminated = {'h', 'e', 'l', 'l', 'o', '\0'}; //null terminator

            //System.Windows.Forms.MessageBox.Show("Hello\0world"); //only prints hello.. stops when it hits the null terminator
        }

        [Test]
        public void Literals()  //embedding a value in source code
        {
            char x = 'x'; //single quotes character literal
            string y = "y\u1234\"asdf"; //double are string literals..\u is unicode
            string z = @"z\0a"; //verbatim string literal...ie can include backslashes and they are not treated specially
            Console.WriteLine(y);
            string a = "first line\r\nsecondline";
            string sampleFile =
                @"heading1  heading2    heading3
value1  value2  value3";
            Regex sampleRegex = new Regex(@"Matches brakcets \(\)");
        }

        //string is a reference type
        //strings are immutable

        [Test]
        public void Assignment()
        {
            string x = "hello"; //writing directions to some object..
            string y = x; //copying the directions..so both refer to same object
            x.Replace('h', 'j'); //effectivly useless.... because it is immutable

            x = x.Replace('h', 'j');
            Console.WriteLine(x);
            Console.WriteLine(y);
            Assert.AreEqual("jello",x);
            Assert.AreEqual("hello",y);
        }

        [Test]
        public void DifferentEqualObjects()
        {
            string x = "hello";
            x = x.Replace('h', 'j');
            object o1 = x;
            object o2 = "jello";
            Assert.AreNotSame(o1,o2);
            Assert.IsFalse(o1==o2);//overloading compile time
            Assert.IsTrue(o1.Equals(o2)); //overriding happens at execution time.. based on their actual type rather than type of variable
        }

        [Test]
        public void DifferentEqualStrings()
        {
            string x = "hello";
            x = x.Replace('h', 'j');
            string s1 = x;
            string s2 = "jello";
            Assert.AreNotSame(s1, s2);
            Assert.IsTrue(s1 == s2);
            Assert.IsTrue(object.Equals(s1,s2)); //slightly safer if one is a null ref then this wont blow up
        }

        [Test]
        public void InterningOfConstants()
        {
            string x = "hello";
            string y = "he" + "llo";
            Assert.AreSame(x,y);
        }

        [Test]
        public void NonInterningOfNonConstants()
        {
            string he = "he";
            string x = "hello";
            string y = he + "llo";
            Assert.AreNotSame(x,y);
            Assert.AreEqual(x,y);
        }

        [Test]
        public void BadConcatenation()
        {
            string simple = new string('x',10000);

            string bad = "";
            for (int i = 0; i < 10000; i++)
            {
                    bad = bad + "x";  //value of bad is a reference..create a new string called bad..so by later iterations it will be copy 900 chars each iteration
            }
            Assert.AreEqual(simple,bad);
        }

        [Test]
        public void GoodConcatenation() //we cant build strings well with strings, as they are immutable
        {
            string simple = new string('x',100000);
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < 100000; i++)
            {
                builder.Append("x"); //rule of thumb.. if using concatenation in a loop use stringBuilder
            }
            string good = builder.ToString();
            Assert.AreEqual(simple,good);
            builder.Append("this wont appear in good");
            Assert.AreEqual(simple, good);
        }

        [Test]
        public void BadUseOfStringBuilder()
        {
            string x = "x";
            string y = "y";
            //we want x + " " + y;
            StringBuilder builder = new StringBuilder();
            builder.Append(x);
            builder.Append(" ");
            builder.Append(y);
            string result = builder.ToString();
            Assert.AreEqual("x y", result);
        }

        [Test]
        public void GoodUseOfConcatenation()
        {
            string x = "x";
            string y = "y";
            string result = x + " " + y;
            Assert.AreEqual("x y", result);
        }

        [Test]
        public void CompilerTranslationofConcatenation()
        {
            string x = "x";
            string y = "y";
            string result = string.Concat(x, " ", y);
            Assert.AreEqual("x y", result);
        }

        [Test]
        public void StringJoin() //nice way of doing csv
        {
            string[] values = {"x", " ", "y"};
            string commaSeperated = string.Join(",", values);
            Assert.AreEqual("x, ,y", commaSeperated);
        }

        [Test]
        public void StringFormat()
        {
            string x = "x";
            string y = "y";
            string result = string.Format("{0} {1}", x,y);
            Assert.AreEqual("x y", result);
        }

        [Test]
        public void StringFormat2()
        {
            string x = "x";
            string y = "y";
            string result = string.Format("{1} {0}", x, y);
            Assert.AreEqual("y x", result);
        }

        [Test]
        public void StringFormat3()
        {
            int x = 100;
            string y = "y";
            string result = string.Format("x={0} y={1}", x, y);
            Assert.AreEqual("x=100 y=y", result);
        }

        [Test]
        public void StringFormat4()
        {
            int value = 100; //also int value = 0x64
            string y = "y";
            string result = string.Format("value=0x{0:x} y={1}", value, y);//notice x here for hex
            Assert.AreEqual("value=0x64 y=y", result);
        }

        [Test]
        public void StringFormat5()
        {
            decimal price = 10.50m;
            string result = string.Format("price={0:c}", price);
            Assert.AreEqual("price=$10.50", result);
        }

        [Test]
        public void InternMethod()
        {
            string x = "hello";
            string y = "jello".Replace('j','h');
            Assert.AreNotSame(x, y);
            string z = string.Intern(y);
            Assert.AreSame(x,z);
        }
| | # 
# Thursday, 24 May 2012
( JonSkeet | TekPub )
[Test]
        public void DisplayValues()
        {
            /*
             * float = System.Single (32 bits)..7 or 8
             * double = System.Double (64 bits)...15 or 16
             * decimal = System.Decimal (128 bits)..28 or 29 significant digits
             *
             * these are all floating point numbers..
             * eg how to multiple 1234.5 by 10... move decimal point
             *
             * sign: 0 (positive/zer) or 1 (negative)
             * exponent (or power) eg where the point ends up eg 2 gives 123.45
             * mantissa eg 12345
            */

            float v1 = 0.2f; //the closest possible representation to 0.2..bause of binary arithmetic
            double v2 = 0.2d; //dont need d really
            Console.WriteLine(50); //default to int
            double half = 50/100; //this is 0!! because it is int 50 / int 100;
            decimal v3 = 0.3m;

            double v5 = v1; //implicit conversion
            float v6 = (float)v3; // has to be explicit

            double x =      0.1;
            x +=            0.000001;
            x +=            0.000001;
            x +=            0.000001;
            x +=            0.000001;
            x +=            0.000001;

            //Assert.AreEqual(0.100005, x); //fails!
            Assert.AreEqual(0.100005, x,0.001); //passes

            //if JonDecimal is only 3 digits
            //JonDecimal x = 1/3;
            //x+x+x = 0.999

            //not a floating point, a decimal point
            //decimal x = 0.1m;

            Console.WriteLine(x.ToString("r")); //round trip.we want to be able to get back

            //when to use decimal
            //use floating point doubles for really big or really small numbers and very quick (> 386/387..floating point co-processors)
            //eg when we don't really need super great precision eg distance sun to earth

            //use decimal when eg 2 pennies + 3 pennies = 5 pennies.. eg 0.05pounds

            //sometimes best way to think of money is ints.. ie 100 pence.
            //decimal twoDollcarsAndFivecents = 2.05m;
            //Console.WriteLine("I have: {0:c}", twoDollcarsAndFivecents); //I have: $2.05

            //decimal value = 2.05m;
            //decimal diviedByTen = value*10;
            //Console.WriteLine(diviedByTen);

            double a = double.NaN; //Not a Number
            double b = double.NaN;
            Console.WriteLine(a == b); //false

            Complex c1 = new Complex(0,1); // 0 + 1i
            Console.WriteLine(c1 * c1);//complex and imaginery numbers

            //for natural numbers which are inherintly vauge eg distance from here to sun use float and double
            //man made quantity eg currency.. decimal is your friend
        }
| | # 
# Sunday, 20 May 2012
( JonSkeet | TekPub )
public class Greeter
{
    //field
    //generally speaking don't give other classes access to your fields
    //can think of it as how it is storing state for the class
    private readonly string speaker;

    //property.. this is public.. the behaviour
    public string Speaker
    {
        get { return speaker; }
        //we've got an immutable type.. something that can't be changed after it is constructed
        //immutable is nice as don't need to worry about change of state
        //set { speaker = value; }
    }

    public Greeter(string speaker)
    {
        //this is referring to current object
        this.speaker = speaker;
    }

    //public methods are part of the API
    public string SayHello(string recipient)
    {
        if (recipient == null)
        {
            throw new ArgumentNullException("recipient");
        }
        if (speaker == null)
        {   
            return "Hello " + recipient;
        }
        return "Hello " + recipient + " from " + speaker;
    }
}

private fields good.. readonly v.good as then we’re immutable therefore easier as don’t need to worry about changes in state

[Test]                                                   
public void SpeakerProperty_IsSetFromConstructor()
{
    Greeter greeter = new Greeter("Rob");
    Assert.AreEqual("Rob", greeter.Speaker);
    Assert.AreNotEqual("rob", greeter.Speaker);
}

asdf

public class Greeter
    {
        //field
        //generally speaking don't give other classes access to your fields
        //can think of it as how it is storing state for the class
        //private string speaker;

        //property.. this is public.. the behaviour
        //public string Speaker
        //{
        //    get { return speaker; }
        //    //we've got an immutable type.. something that can't be changed after it is constructed
        //    //immutable is nice as don't need to worry about change of state

        //    //value is a contextual keyword
        //    set { speaker = value; }
        //}

        //auto props introduced in C#3
        //with private property is now immutable..however not quite as could change it in this class
        //if want to protect against this, then make a backing field with readonly like above
        public string Speaker { get; private set; }

        public Greeter(string speaker)
        {
            //this is referring to current object
            this.Speaker = speaker;
        }

asdf

public class Greeter
{
    //field
    //generally speaking don't give other classes access to your fields
    //can think of it as how it is storing state for the class
    //private string speaker;

    //property.. this is public.. the behaviour
    //public string Speaker
    //{
    //    get { return speaker; }
    //    //we've got an immutable type.. something that can't be changed after it is constructed
    //    //immutable is nice as don't need to worry about change of state

    //    //value is a contextual keyword
    //    set { speaker = value; }
    //}

    //auto props introduced in C#3
    //with private property is now immutable..however not quite as could change it in this class
    //if want to protect against this, then make a backing field with readonly like above
    public string Speaker { get; set; }
    //private readonly string speaker;
    //public string Speaker
    //{
    //    get
    //    {
    //        Console.WriteLine("Returning speaker = " + speaker);
    //        return speaker;
    //    }
    //}

    public Greeter(string speaker)
    {
        this.Speaker = speaker;
    }

    //public methods are part of the API
    public string SayHello(string recipient)
    {
        if (recipient == null)
        {
            throw new ArgumentNullException("recipient");
        }
        if (Speaker == null)
        {   
            return "Hello " + recipient;
        }
        return "Hello " + recipient + " from " + Speaker;
    }

auto properties.  Backing fields.

| | # 
( JonSkeet | TekPub )

public class Greeter
    {
        //adding a parameter
        public string SayHello(string recipient)
        {
            //return "Hello " + recipient;
            return string.Concat("Hello ",recipient);
        }
    }

compiled changes the + to a string.Concat

[TestFixture]
public class GreeterTest
{
    [Test]
    public void SayHello_ReturnsHelloWithReceipientName()
    {
        Greeter greeter = new Greeter();
        //adding an argument
        string greeting = greeter.SayHello("Jon");
        Assert.AreEqual("Hello Jon", greeting);
    }
}
//constructor is used to build an instance of a class, an object
//if no constructor the compiler will make one for us.
//which calls the base class constructor..
public Greeter() : base()
{
}

adding a constructor (ctor)

public class Greeter
    {
        //a private field..if it is only set within the constructor then set it readonly
        //the = "asdf" is a variable initialiser
        private readonly string speaker = "Rob";

        public Greeter(string speaker)
        {
            this.speaker = speaker;
        }

        public string SayHello(string recipient)
        {
            return "Hello " + recipient + " from " + speaker;
        }
    }

variable initialiser.. and readonly field

[TestFixture]
public class GreeterTest
{
    [Test]
    public void SayHello_ReturnsHelloWithReceipientNameAndSpeakerName()
    {
        Greeter greeter = new Greeter("Rob");
        string greeting = greeter.SayHello("Jon");
        Assert.AreEqual("Hello Jon from Rob", greeting);
    }

    [Test]
    public void CanConstructingGreeterWithoutSpeakerName()
    {
        //null here... is a special kind of reference.. ie a blank piece of paper with directions to nowhere
        //it is not an empty string
        new Greeter(null);
    }

    [Test]
    public void SayHello_ReturnsHelloWithReceipientNameButNoSpeakerName()
    {
        Greeter greeter = new Greeter(null);
        string greeting = greeter.SayHello("Jon");
        Assert.AreEqual("Hello Jon", greeting);
    }

    [Test]
    public void SayHello_ThrowsExceptionWithNullReceipient()
    {
        Greeter greeter = new Greeter("Rob");
        //Assert.Throws<ArgumentNullException>(() => greeter.SayHello(null));
        Assert.Throws(typeof (ArgumentNullException), delegate
                                                          {
                                                              greeter.SayHello(null);
                                                          });
    }

null references.

public class Greeter
{
    //a private field..if it is only set within the constructor then set it readonly
    //the = "asdf" is a variable initialiser
    private readonly string speaker;

    public Greeter(string speaker)
    {
        this.speaker = speaker;
    }

    public string SayHello(string recipient)
    {
        if (recipient == null)
        {
            throw new ArgumentNullException("recipient");
        }
        if (speaker == null)
        {   
            return "Hello " + recipient;
        }
        return "Hello " + recipient + " from " + speaker;
    }
}

variable initialiser.  readonly fields – use where only set in the constructor

| | # 
( JonSkeet | TekPub )

an assembly is a library or executable or website

System.Core   are the standard(ish) libraries..more general

Microsoft.CSharp  .. are something lke the mono team would create their own ones..? eg Win32 specific..but mono would probably have to do a Microsoft.CSharp..

image

Jon doesn’t like warnings.. there is a VS setting to make all warnings errors.

[TestFixture]
//PascalCase
public class GreeterTest
{
    [Test]
    public void SayHello_ReturnsHello()
    {
        //declaring a variable of type Greeter.
        //calling the constructor
        //assign the value back from the constructor to greeter
        //the value of the greeter variable is 'directions' to the Greeter... way of getting to the object
        //eg directions to house of a bit of paper
        //ie it is the reference type
        Greeter greeter = new Greeter();
        //this has the same reference.. there is only 1 instance of greeter
        //the value isn't the object
        Greeter theSameGreeter = greeter;
        //camelCase
        //Greeter greeterOther;

        //all types begin with Capital
        //string, int, unit, byte, object.. alias for full type name System.String ... int is to System.Int32
        //not Random
        //string (System.String) is a reference type
        string greeting = greeter.SayHello();
        //passing in arguments.. a string literal
        Assert.AreEqual("Hello", greeting);
    }
}

Jon describing in detail 3 lines of code.

//a class is a sort of blueprint of an object
    //some information
    //some associated behaviours
    //eg a house...
    //colour walls are, colour windows are...
    //behaviour change colour, turn on heating
    public class Greeter
    {
        //behaviour is usually in methods in c#
        public string SayHello()
        {
            return "Hello";
        }
    }
| | # 
# Saturday, 19 May 2012

Supposed to be the introduction episode Smile

Dynamic

static void Main(string[] args)
        {
            object x = new List<int>();
            //will give an InvalidCastException at runtime
            string y = (string) x;
            Console.WriteLine(y.Length);
        }
object x = "hello";
            string y = (string) x;
            Console.WriteLine(y.Length);

gives answer of 5

object x = null;
            //we can cast a null reference
            string y = (string)x;
            //but we cant dereference it..get a nullReferenceException
            Console.WriteLine(y.Length);

sdf

//don't think of x at any type... sort out at execution time
dynamic x = "hello";
//5
Console.WriteLine(x.Length);

//an array
x = new int[] {10, 20, 30 };
//3
Console.WriteLine(x.Length);

from

int x = 123;
            int y = 10;
            Console.WriteLine(x-y);

image

using ildasm to disassemble the debug assembly.  The nop statements are for debug.

This is op code (IL).. i4 is like int32

load 123 and put into stack position 0

load 10 and put into stack position 1

then put into dynamic types

Named Arguments

Whats an argument and whats a parameter?

    static void Main(string[] args)
    {
        //provide an argument
        Foo("hello");
    }

    //x is a parameter
    static void Foo(string x)
    {
        Console.WriteLine(x);
    }
}

image

Got it the wrong way round.. hard to tell which is which in MessageBox.Show

static void Main(string[] args)
        {
            //named argument C#4
            Foo(x: "hello", y:"Rob");
            //referenced System.Windows.Forms
            MessageBox.Show(caption:"title", text:"body");
        }

        //x is a parameter
        static void Foo(string x, string y)
        {
            Console.WriteLine(x + " " + y);
        }

better!

Optional Parameters

    static void Main(string[] args)
    {
        //named arguments
        Foo(y: "Rob");
        Foo(y: "Dave");
        Foo(y: "Mike");
        Foo(y: "Bill");
        Foo("Hi", "Anders");
        Foo();
    }

    //optional parameters
    //if first parameter is optional all have to be
    static void Foo(string x = "Hello", string y = "Everone")
    {
        Console.WriteLine(x + " " + y);
    }
}

Covariance and Contravariance

Some code here.. poster child of the more used covariance is IEnumerable<T>.. look for out keword.  And it is to do with hierarchies.

class Fruit { }
    class Banana : Fruit { }
    class Apple : Fruit { }

    //interface IEnumerable<out T>
    //{
    //    IEnumerator<T> GetEnumerator();
    //}

    //interface IEnumerator<out T> : IDisposable
    //{
    //    T Current { get; }
    //    bool MoveNext();
    //    void Reset();
    //}

    //covariance values coming out of an interface
    //usually happens with IEnumerable of T
    interface IFoo<out T>
    {
        T GiveMeAnInstanceOfT();
        //void TakeanInstanceOfT(T instance);
    }

    //contravariance is in

    class Program
    {
        static void Main(string[] args)
        {
            //List<Banana> bunchOfBananas = new List<Banana>();
            IFoo<Banana> bunchOfBananas = null;

            //cant convert from a list of banana to a list of fruit
            //List<Fruit> fruitBowl = new List<Banana>();

            //List<Fruit> fruitBowl = bunchOfBananas;
            //fruitBowl.Add(new Apple());

            //Banana banana = bunchOfBananas[0];

            //IEnumerable - sequence..cant add.. can only observe
            //IEnumerable<Fruit> fruitBowl = bunchOfBananas;
            IFoo<Fruit> fruitBowl = bunchOfBananas;
        }
    }
| | # 
( JonSkeet | TekPub )

When constructors get out of control and Factory gets cumbersome.

[TestFixture]
    public class BuilderTests
    {
        [Test]
        public void BuilderPattern()
        {
            Period period = Period.FromHours(5);
            //gets longwinded
            period = Period.FromHours(5) + Period.FromMinutes(3);

            //mandatory stuff in constructor
            //eg if this were an EmailBuilder then to, from etc..
            //PeriodBuilder builder = new PeriodBuilder();
            ////option stuff
            //builder.Hours = 5;
            //builder.Minutes = 3;
            //Period built = builder.Build();

            //using object initialiser syntax C#3
            Period built = new PeriodBuilder { Hours = 5, Minutes = 3 }.Build();

            //this wont change anything
            //builder.Seconds = 10;
            Assert.AreEqual(0, built.Seconds);
            Assert.AreEqual(built, period);
        }
    }
| | # 
( JonSkeet | TekPub )
//this is an immutable type
    public sealed class Point
    {
        //field
        private readonly int x;
        private readonly int y;

        //property
        public int X { get { return x; } }
        public int Y { get { return y; } }

        public Point(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    }

asdf

public struct BadDuration
   {
       private readonly long seconds;
       private readonly long milliseconds;
       private readonly long ticks;

       //multiple constructors are a code smell and can mean you're trying to do too much with a single class or struct
       public BadDuration(long ticks)
       {
           this.ticks = ticks;
       }

       public BadDuration(long milliseconds)
       {
           this.ticks = milliseconds * 10000;
       }

       public BadDuration(long seconds)
       {
           this.ticks = seconds * 10000 * 1000;
       }
   }

wont compile as signatures are the same eg all are longs

public struct BadDuration
   {
       //fields
       //private readonly long seconds;
       //private readonly long milliseconds;
       private readonly long ticks;

       //property
       public long Ticks { get { return ticks; } }

       //this works in a class.. sort of immutable

       //multiple constructors are a code smell and can mean you're trying to do too much with a single class or struct
       private BadDuration(long ticks)
       {
           this.ticks = ticks;
       }
        
       public static BadDuration FromTicks(long ticks)
       {
           return new BadDuration(ticks);
       }

       //the classic Factory pattern that can help clear up a constructor overload mess.  downside is requires a knowledge of your api.
       public static BadDuration FromMilliseconds(long milliseconds)
       {
           return new BadDuration(milliseconds * 10000);
       }

       public static BadDuration FromSeconds(long seconds)
       {
           return new BadDuration(seconds * 10000 * 1000);
       }
   }

    //immutable - state cannot be modified after it has been created
    [TestFixture]
    public class SimpleImmutability
    {
        [Test]
        public void FromSeconds()
        {
            BadDuration duration = BadDuration.FromMilliseconds(5);
            Assert.AreEqual(50000, duration.Ticks);
        }

        [Test]
        public void Ticks()
        {
            BadDuration duration = BadDuration.FromTicks(10);
            Assert.AreEqual(10, duration.Ticks);
        }
    }

very interesting code with with classic Factory pattern.  Very nice way of easily making objects.

| | # 
( JonSkeet | TekPub )

Designing types and using types.

“Single Responsibility Principle” every class should be responsible for only one thing.  Part of this is being completely clear about what the class does

Try to have types that represent what you want them to.

Summary for DateTime:

  • can’t represent just a date
  • can’t represent just a time of day
  • got to use same time whether universal time, this computer, another timezone
| | # 
# Friday, 18 May 2012
( IoC | JonSkeet | TekPub )

In addition to handling instance construction, Inversion of Control containers can also handle lifetime and scope for you.

image

//.InSingletonScope resolve it later on, but resolve it only once, use the same instance after that.
//injector.Bind<IClock, SystemClock>().InSingletonScope();

.InSingletonScope resolve it later on, but resolve it only once, use the same instance after that.

Testability!

singletons – global state is the enemy of simplicity! let IoC containers do stuff.

logging is okay as its fine generally to have all the system call into the same logger

for the clock – Jon is always using an interface, and DI.

| | # 
( Factory | JonSkeet | TekPub )

Taking the manually done dependency injection and using a factory now (then go away from factory to home grown  IoC)

//is this unneeded complexity if its a smaller app?  Actually this is a Factory
    //jon recommends if can keep in main method, then keep manual DI.
    class Injector
    {
        //getting ugly as can be literally 100's of dependencies
        public IClock CreateClock()
        {
            //a singleton
            return SystemClock.Instance;
        }

        public Licence CreateLicence()
        {
            return new Licence(Instant.UnixEpoch, CreateClock());
        }

        public DateTimeZone CreateTimeZone()
        {
            return DateTimeZone.GetSystemDefault();
        }

        public CalendarSystem CreateCalendarSystem()
        {
            return CalendarSystem.Iso;
        }

        public Diary CreateDiary()
        {
            return new Diary(CreateClock(),  CreateCalendarSystem(), CreateTimeZone());
        }

        public DiaryPresenter CreateDiaryPresenter()
        {
            return new DiaryPresenter(CreateDiary(), CreateLicence());
        }
    }

 

and then:

static void Main()
        {
            // newing up the factory
            Injector injector = new Injector();
            var presenter = injector.CreateDiaryPresenter();
            presenter.Start();
        }

outtake to video 5..outtake…IoC.  Basically wanting to make things more generic:

structuremap, ninject, autofac, Unity are IoC

eg in an MVC app I  http://www.programgood.net/2011/09/20/VidPub1SettingUpSolution.aspx:

“Every time you see a request for ILogger interface in a controller, return a new NLogger class”

kernel.Bind<ILogger>().To<NLogger>();
[TestFixture]
public class Program
{
    [Test]
    public void MainTest()
    {
        //manually setting up the dependencies
        IClock clock = SystemClock.Instance;
        Diary diary = new Diary(clock, CalendarSystem.Iso, DateTimeZone.GetSystemDefault());
        //licence expired in 1970, and current time is systemclock time
        Licence licence = new Licence(Instant.UnixEpoch, clock);
        var presenter = new DiaryPresenter(diary, licence);
        presenter.Start();

        //IoC
        //Injector injector = new Injector();
        //injector.Bind<IClock, SystemClock>();
        //injector.Bind<DateTimeZone>(DateTimeZone.GetSystemDefault());
        //injector.Bind<Instant>(Instant.FromUtc(2000,1,1,0,0,0));
        //injector.Bind<CalendarSystem>(CalendarSystem.Iso);

        ////you've got all these things.. now do stuff please
        //var presenter = injector.Resolve<DiaryPresenter>();
        //presenter.Start();

        
    }
}

class DiaryPresenter
{
    private readonly Diary diary;
    private readonly Licence licence;

    public DiaryPresenter(Diary diary, Licence licence)
    {
        this.diary = diary;
        this.licence = licence;
    }

    public void Start()
    {
        Console.WriteLine("Today is {0}", diary.FormatToday());
        Console.WriteLine("Licence expired? {0}", licence.HasExpired);
    }
}

class Licence
{
    //fields
    private readonly Instant expirey;
    private readonly IClock clock;

    public Licence(Instant expirey, IClock clock)
    {
        //variables or local variables
        this.expirey = expirey;
        this.clock = clock;
    }

    //property
    public bool HasExpired
    {
        get { return clock.Now >= expirey; }
    }
}

//calendaring application which will want to know what time it is too!
class Diary
{
    private readonly LocalDatePattern outputPattern = LocalDatePattern.CreateWithInvariantInfo("yyyy-MM-dd");
    //fields
    private readonly IClock clock;
    private readonly CalendarSystem calendar;
    private readonly DateTimeZone timeZone;

    //by demanding the dependencies in the constructor, classes are more flexible
    //especially if they are interfacess
    public Diary(IClock clock, CalendarSystem calendar, DateTimeZone timeZone)
    {
        this.clock = clock;
        this.calendar = calendar;
        this.timeZone = timeZone;
    }

    public string FormatToday()
    {
        //in system default timezone, and system default calendar
        //DateTime dateTime = DateTime.Today;
        LocalDate date = clock.Now.InZone(timeZone, calendar).LocalDateTime.Date;
        if (date.Month == 4)
        {  //ncrunch showing black here - so tests are not covering this codepath
            return "April fool";
        }
        return outputPattern.Format(date);
    }
}

A working version of the code with manual DI.

class Program
    {
        static void Main(string[] args)
        {
            //manually setting up the dependencies
            IClock clock = SystemClock.Instance;
            Diary diary = new Diary(clock, CalendarSystem.Iso, DateTimeZone.GetSystemDefault());
            //licence expired in 1970, and current time is systemclock time
            Licence licence = new Licence(Instant.UnixEpoch, clock);
            var presenter = new DiaryPresenter(diary, licence);
            presenter.Start();


            Console.WriteLine("Type in 1 for good licence, 2 for expired");
            string userInput = Console.ReadLine();
            if (userInput == "1")
            {
                //really need public properties on licence to reset it rather than instantiating a new one!
                licence = new Licence(Instant.FromUtc(2020,1,1,0,0,0), clock);
                presenter = new DiaryPresenter(diary, licence);
            }
            Console.WriteLine("License expiredx: {0}", licence.HasExpired);
            Console.ReadLine();
        }
    }

Made a new console project referencing the class project.  Proves that it does work as a real application and not just in test.

class Injector
{
    //going to be able to bind by instance and by type
    //where TConcrete derives from TKey
    //TKey is going to be what we provide

    //from type to a way of getting to an instance of that type
    private Dictionary<Type,Func<object>> providers = new Dictionary<Type, Func<object>>();

    //eg whenever you want IClock, use the SystemClock type
    public void Bind <TKey, TConcrete>() where TConcrete : TKey
    {
        //where we're
        providers[typeof(TKey)] = () => ResolveByType(typeof(TConcrete));
    }

    private object ResolveByType(Type type)
    {
        Console.WriteLine("Resolving...{0}", type);
        //assume we're got a single constructor in the type we're passing in
        var constructor = type.GetConstructors().SingleOrDefault();
        //if we don't have a constructor then maybe a static method
        if (constructor != null)
        {
            //want to invoke the constructor, but need to resolve all of its dependencies
            //eg when we ask for a diary, get me a clock, get me a calendar, get me a timezone
            var arguments = constructor.GetParameters()
                                       .Select(parameterInfo => Resolve(parameterInfo.ParameterType))
                                       .ToArray();
            return constructor.Invoke(arguments);
        }
        //Instance is a property on system clock
        //we're trying to find something on systemclock... however it was a field, thats why GetProperty wasn't returning it.
        //var instanceProperty = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static);
        var instanceField = type.GetField("Instance");
        return instanceField.GetValue(null);
    }

    public void Bind<T>(T instance)
    {
        //returns the instance
        providers[typeof(T)] = () => instance;
    }

    internal TKey Resolve<TKey>()
    {
        return (TKey)Resolve(typeof(TKey));
    }

    //how do we resolve something?
    internal object Resolve(Type type)
    {
        Func<object> provider;

        if (providers.TryGetValue(type, out provider))
        {
            return provider();
        }
        return ResolveByType(type);
    }
}

need to come back to this and understand**

| | # 
# Thursday, 17 May 2012
( TekPub )

Any time you instantiate or reference a concrete type within a class, you take a Dependency and make your code harder to test.

public Licence(Instant expirey, IClock clock)
        {
            //variables or local variables
            this.expirey = expirey;
            this.clock = clock;
        }

we are injecting a dependency here.  More loosely bound here than


public Licence(Instant expirey)
{
    //variables or local variables
    this.expirey = expirey;
    this.clock = SystemClock.Instance;
}

tightly bound to a concrete implementation here.

We made another class here called Diary which uses a clock too:

//calendaring application which will want to know what time it is too!
    class Diary
    {
        private readonly LocalDatePattern outputPattern = LocalDatePattern.CreateWithInvariantInfo("yyyy-MM-dd");
        //fields
        private readonly IClock clock;
        private readonly CalendarSystem calendar;
        private readonly DateTimeZone timeZone;

        //by demanding the dependencies in the constructor, classes are more flexible
        //especially if they are interfacess
        public Diary(IClock clock, CalendarSystem calendar, DateTimeZone timeZone)
        {
            this.clock = clock;
            this.calendar = calendar;
            this.timeZone = timeZone;
        }

        public string FormatToday()
        {
            //in system default timezone, and system default calendar
            //DateTime dateTime = DateTime.Today;
            LocalDate date = clock.Now.InZone(timeZone, calendar).LocalDateTime.Date;
            if (date.Month == 4)
            {  //ncrunch showing black here - so tests are not covering this codepath
                return "April fool";
            }
            return outputPattern.Format(date);
        }
    }

 

//still a class lib so can't run it.. demonstrates concept
    public class Program
    {
        static void Main()
        {
            //manual dependency injection - this takes a lot of time and code to do
            //so people invented dependency injection frameworks aka Inversion of Control.
            IClock clock = SystemClock.Instance;

            Licence licence = new Licence(Instant.UnixEpoch, clock);
            Diary diary = new Diary(clock,CalendarSystem.Iso, DateTimeZone.GetSystemDefault());

            DiaryPresenter presenter = new DiaryPresenter(diary, licence);
        }
    }

    class DiaryPresenter
    {
        public DiaryPresenter(Diary diary, Licence licence)
        {
        }
    }

    class Licence
    {
        private readonly Instant expirey;
        private readonly IClock clock;

        public Licence(Instant expirey, IClock clock)
        {
            //variables or local variables
            this.expirey = expirey;
            this.clock = clock;
        }

        //property
        public bool HasExpired
        {
            get { return clock.Now >= expirey; }
        }
    }

    //calendaring application which will want to know what time it is too!
    class Diary
    {
        private readonly LocalDatePattern outputPattern = LocalDatePattern.CreateWithInvariantInfo("yyyy-MM-dd");
        //fields
        private readonly IClock clock;
        private readonly CalendarSystem calendar;
        private readonly DateTimeZone timeZone;

        //by demanding the dependencies in the constructor, classes are more flexible
        //especially if they are interfacess
        public Diary(IClock clock, CalendarSystem calendar, DateTimeZone timeZone)
        {
            this.clock = clock;
            this.calendar = calendar;
            this.timeZone = timeZone;
        }

        public string FormatToday()
        {
            //in system default timezone, and system default calendar
            //DateTime dateTime = DateTime.Today;
            LocalDate date = clock.Now.InZone(timeZone, calendar).LocalDateTime.Date;
            if (date.Month == 4)
            {  //ncrunch showing black here - so tests are not covering this codepath
                return "April fool";
            }
            return outputPattern.Format(date);
        }
    }

Manually doing dependency injection.  Setting up each component explicitly.  Each is loosely coupled

Licences don’t know about Diaries

Diaries don’t know about Licences..

DiaryPresenter knows about diary and licence, but not about a clock or timezone directly.

notice SystemClock.Instance is a singleton.

can get very hard to maintain

| | # 
# Wednesday, 16 May 2012

Why are interfaces important?

not a pattern.. a language feature.

time zone changes..

We want to give the current Date and Time as a dependency.. so can test properly eg

what if our licence never expires in following 5 years.. want to inject what would happen in the future,  and using DateTime.Now in our licence code means can’t test that.

[TestFixture]
  public class LicenceTests
  {
      [Test]
      public void HasExpired_AnExpiredDate_ReturnFalse()
      {
          Licence licence = new Licence(new DateTime(2000,1,1,0,0,0));
          Assert.IsTrue(licence.HasExpired);
      }

      [Test]
      public void HasExpired_AFutureDate_ReturnTrue()
      {
          Licence licence = new Licence(new DateTime(2020, 1, 1, 0, 0, 0));
          Assert.IsFalse(licence.HasExpired);
      }
  }

  class Licence
  {
      //field
      private readonly DateTime expirey;

      public Licence(DateTime expirey)
      {
          //expirey is a variable or local variable
          this.expirey = expirey;
      }

      //property
      public bool HasExpired
      {
          //a dependency on a static method
          //nothing we can do to make it behave differtly in tests  
          get { return DateTime.UtcNow > expirey; }
      }
  }

 

StubClock and SystemClock both implement IClock

public interface IClock
    {
        /// <summary>
        /// Gets the current <see cref="Instant"/> on the time line according to this clock.
        /// </summary>
        Instant Now { get; }
    }

so thats how this code uses interfaces.. for testing we’ve got a StubClock that we can set the time on.  For production we pass in the actual time.

[TestFixture]
public class LicenceTests
{
    [Test]
    public void HasExpired_AnExpiredDate_ReturnTrue()
    {
        Instant expirey = Instant.FromUtc(2000, 1, 1, 0, 0, 0);
        StubClock clock = new StubClock(expirey + Duration.FromTicks(1));

        //injecting the dependency
        Licence licence = new Licence(expirey, clock);

        Assert.IsTrue(licence.HasExpired);
    }

    [Test]
    public void HasExpired_AFutureDate_ReturnTrue()
    {
        Instant expirey = Instant.FromUtc(2000, 1, 1, 0, 0, 0);
        StubClock clock = new StubClock(expirey - Duration.FromTicks(1));

        Licence licence = new Licence(expirey, clock);

        Assert.IsFalse(licence.HasExpired);
    }

    [Test]
    public void HasExpired_AtExactInstant_ReturnTrue()
    {
        Instant expirey = Instant.FromUtc(2000, 1, 1, 0, 0, 0);
        StubClock clock = new StubClock(expirey);

        Licence licence = new Licence(expirey, clock);

        Assert.IsTrue(licence.HasExpired);
    }

    [Test]
    public void HasExpired_NonExpiredLicenceBecomesExpires_ReturnTrue()
    {
        Instant expirey = Instant.FromUtc(2000, 1, 1, 0, 0, 0);
        StubClock clock = new StubClock(expirey - Duration.FromTicks(1));

        Licence licence = new Licence(expirey, clock);

        Assert.IsFalse(licence.HasExpired);
        clock.AdvanceTicks(1);
        Assert.IsTrue(licence.HasExpired);
    }
}

class Licence
{
    private readonly Instant expirey;
    private readonly IClock clock;

    public Licence(Instant expirey, IClock clock)
    {
        //variables or local variables
        this.expirey = expirey;
        this.clock = clock;
    }

    //property
    public bool HasExpired
    {
        get { return clock.Now >= expirey; }
    }
}

public class BigApplicatiion
{
    static void Main ()
    {
        //a natural singleton!  there is only 1 system clock
        //but there is no way to test this business code...want dependency injection
        Licence licence = new Licence(Instant.FromUtc(2012,4,19,0,0), SystemClock.Instance);
        if (licence.HasExpired)
        {
            Console.WriteLine("Licence expired");
            return;
        }
    }
}
| | # 
( Patterns | TekPub )

Singleton: A class which only allows a single instance

Very controversial in general.

NodaTime – Jons open source library, which implements good practices

namespace Sandbox
{
    public class Singleton
    {
        public void DoSomething()
        {
        }
    }

    public class SingletonClient
    {
        public void UseSingleton()
        {
            Singleton s1 = new Singleton();
            s1.DoSomething();
            Singleton s2 = new Singleton();
            s2.DoSomething();
        }
    }
}

Ahh – can make 2 of the singleton class!

public static class Singleton
    {
        public static void DoSomething()
        {
        }
    }

    public class SingletonClient
    {
        public void UseSingleton()
        {
            //Singleton s1 = new Singleton();
            //s1.DoSomething();
            //Singleton s2 = new Singleton();
            //s2.DoSomething();
            Singleton.DoSomething();
        }
    }

but want to instantiate class.. just not have 2 possible

public class Singleton
{
    //global state - bad
    private static Singleton instance;

    private Singleton()
    {
    }

    public static Singleton CreateInstance()
    {
        if (instance == null)
        {
            instance = new Singleton();
        }
        return instance;
    }

    //raison d'etre for the class
    public void DoSomething()
    {
    }
}

[TestFixture]
public class SingletonClient
{
    [Test]
    public void UseSingleton()
    {
        Singleton s1 = Singleton.CreateInstance();
        Singleton s2 = Singleton.CreateInstance();
        Assert.AreSame(s1,s2);
    }
}

However if on multiple threads this could be bad as both could get to the new Singleton() line at the same time.

mutex locks..complex

public class Singleton
{
    //clr manages locking, mutex and volatile stuff
    private static readonly Singleton instance = new Singleton();

    //empty static constructor - chaanges when the clr is allowed to initialise this...
    //will only initialise before it is first used.
    static Singleton() {}

    private Singleton()
    {
        //stuff that must only happen once
        Console.WriteLine("Singleton constructor");
    }

    public static Singleton Instance { get { return instance; } }

    public static void SayHi()
    {
        Console.WriteLine("hi");
    }

    //raison d'etre for the class
    public void DoSomething()
    {
        // This must be thread-safe... it can be got at from multiple threads... thats its purpose
    }
}

[TestFixture]
public class SingletonClient
{
    [Test]
    public void UseSingleton()
    {
        Singleton.SayHi();
        Console.WriteLine("Start of test");
        Singleton s1 = Singleton.Instance;
        Singleton s2 = Singleton.Instance;
        Assert.AreSame(s1,s2);
    }
}

asdf

image

but say we wanted real laziness ie only creating the singleton when needed:

public class Singleton
    {
        //nested class
        private static class SingletonHolder
        {
            internal static readonly Singleton instance = new Singleton();
            //empty static constructor - forces laziness!
            static SingletonHolder() {}
        }

        private Singleton()
        {
            //stuff that must only happen once
            Console.WriteLine("Singleton constructor");
        }

        public static Singleton Instance { get { return SingletonHolder.instance; } }

        public static void SayHi()
        {
            Console.WriteLine("hi");
        }

        //raison d'etre for the class
        public void DoSomething()
        {
            // This must be thread-safe... it can be got at from multiple threads... thats its purpose
        }
    }

    [TestFixture]
    public class SingletonClient
    {
        [Test]
        public void UseSingleton()
        {
            Singleton.SayHi();
            Console.WriteLine("Start of test");
            Singleton s1 = Singleton.Instance;
            Singleton s2 = Singleton.Instance;
            Assert.AreSame(s1,s2);
        }
    }

.NET4 could use Lazy<T>

| | # 
# Friday, 30 December 2011
( Patterns | TDD | TekPub )

“An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object.”

eg every time we call Add, we want a notification to clients (logger) that something interesting happened.

  • publisher
  • subscriber

Action<string>

- if we were in .NET2 then public event would have to be of some delegate type.

-  Would have to declare a delegate type of function that would return a string

3.5  Action<T>

public class StringCalculator
    {
        //declare and assign it at the same time (so don't have to check it is null every time)
        public event Action<string> OnAdd = delegate { };

        private readonly ILogger logger;
        public ILogger SecondaryLogger { get; set; }

        public StringCalculator(ILogger logger)
        {
            this.logger = logger;
        }

        public int Add(string numbers)
        {
            OnAdd.Invoke(numbers);
            LogNumbers(numbers);
            if (IsEmpty(numbers))
            {
                return DefaultEmptyResult();
            }
            return AllOtherValues(numbers);
        }

declaring the event, and invoking when add is pressed:

[Test]
        public void Add_Always_TriggersOnAddEvent()
        {
            //bool wasTriggered = false;
            string eventParam = null;

            StringCalculator sc = GetDefaultCalc();
            //lambda way
            //sc.OnAdd += s => wasTriggered = true;

            //so whenever someone invokes the event, wasTriggered will turn to true
            //sc.OnAdd += delegate(string s) { wasTriggered = true; };
            
            //register for event
            sc.OnAdd += delegate(string s) { eventParam = s; };

            sc.Add("1");

            //Assert.IsTrue(wasTriggered);
            Assert.AreEqual("1", eventParam);
        }

subscribing to event, passing in a delegate

Extract and Override

very powerful as can break dependencies easily without interfaces

| | # 
# Wednesday, 28 December 2011
( TDD | TekPub )

Interaction tests.. ie interaction between objects..usually have to replace one of the objects

source control:

  • git init,
  • git add .
  • git commit –am “initial load”

going back to simple stuff:

If we have a Fake object and we do Asserts against it, it is a Mock object:

//interaction tests!
        [Test]
        public void Add_EmptyString_CallsTheLogger()
        {
            FakeLogger fakeLog = new FakeLogger();
            StringCalculator sc = new StringCalculator(fakeLog);

            sc.Add("");

            StringAssert.Contains("empty", fakeLog.WrittenWith);
        }

poor mans injecting into the constructor a logger

    public class StringCalculator
    {
        private readonly ILogger logger;

        public StringCalculator(ILogger logger)
        {
            this.logger = logger;
        }

        public int Add(string numbers)
        {
            LogNumbers(numbers);
            if (IsEmpty(numbers))
            {
                return DefaultEmptyResult();
            }
            return AllOtherValues(numbers);
        }

        private void LogNumbers(string numbers)
        {
            if (IsEmpty(numbers))
                logger.Write("empty");
            else
                logger.Write(numbers);
        }

        private bool IsEmpty(string numbers)
        {
            return string.IsNullOrEmpty(numbers);
        }

        private static int AllOtherValues(string numbers)
        {
            return int.Parse(numbers);
        }

        private static int DefaultEmptyResult()
        {
            return 0;
        }

 

Call a WebService if the log is full

[TestCase("1")]
        [TestCase("2")]
        [TestCase("333")]
        public void Logging_SingleNumberAndFirstLoggerIsFull_SecondaryLoggerIsCalled(string number)
        {
            FakeLogger firstLogger = new FakeLogger();
            FakeLogger secondLogger = new FakeLogger();

            firstLogger.WillThrow = new Exception("out of space");
            StringCalculator sc = new StringCalculator(firstLogger);
            sc.SecondaryLogger = secondLogger;

            sc.Add(number);

            //secondaryLogger is the mock object
            StringAssert.Contains(number, secondLogger.WrittenWith);
        }

the first test, which then became a testCase.

        public int Add(string numbers)
        {
            LogNumbers(numbers);
            if (IsEmpty(numbers))
            {
                return DefaultEmptyResult();
            }
            return AllOtherValues(numbers);
        }

        private void LogNumbers(string numbers)
        {
            try
            {
                if (IsEmpty(numbers))
                    logger.Write("empty");
                else
                    logger.Write(numbers);
            }
            catch (Exception e)
            {
                SecondaryLogger.Write(numbers);
            }
        }

nice having logic at same level of abstraction.

| | # 
# Tuesday, 27 December 2011
( kata | TDD | TekPub )

Code Kata are exercises that you can do

osherove.com/kata

  • 1 method, 1 parameter
  • 0 or more numbers
  • seperated by a comma

eg var sum = Calculator.Sum(1,3,10);

Alt N for PackageManagerConsole.

Start with simplest test..empty string.

[TestFixture]
    public class StringCalculatorTests
    {
        [Test]
        public void Add_EmptyString_ReturnsZero()
        {
            //start with this even though StringCalculator doesn't exist yet
            StringCalculator sc = new StringCalculator();

            //method doesn't exist
            int result = sc.Add("");

            //first kind of syntax
            //Assert.AreEqual(0, result);
            //second kind of syntax
            Assert.That(result, Is.EqualTo(0));
        }

        [Test]
        public void Add_SingleNumber_ReturnsThatSingleNumber()
        {
            StringCalculator sc = new StringCalculator();

            int result = sc.Add("1");

            Assert.AreEqual(1, result);
        }
    }

    public class StringCalculator
    {
        public int Add(string numbers)
        {
            return 0;
        }
    }

just about to get the 2nd test passing… notice no refactoring yet as only do that when 2 tests are actually passing!

Just assigned Alt Y to rerun all tests so can keep the cursor in the add method.

Ctrl Alt P – assign parameter

String Calc – first bits

nCover

image_thumb1

100% code coverage at the moment.

[TestCase("1,2",3)]
[TestCase("1,3",4)]
[TestCase("4,5",9)]
[TestCase("14,44",58)]
[TestCase("1,2,3", 6)]
[TestCase("1,2,3,4,5", 15)]
public void Add_MultipleNumbers_ReturnsTheSum(string numbers, int expected)
{
StringCalculator sc = MakeCalc();

int result = sc.Add(numbers);

Assert.AreEqual(expected, result);
}

private static StringCalculator MakeCalc()
{
return new StringCalculator();
}
}

public class StringCalculator
{
public int Add(string numbers)
{
if (numbers.Length == 0)
return 0;
if (numbers.Length == 1)
return int.Parse(numbers);

var listOfNumbers = numbers.Split(',');
int sumOfNumbers = 0;
foreach (var number in listOfNumbers)
sumOfNumbers += int.Parse(number);

return sumOfNumbers;

}
}

first shot at getting multiple numbers being summed together

[TestFixture]
    public class StringCalculatorTests
    {
        private static StringCalculator MakeCalc()
        {
            return new StringCalculator();
        }

        [Test]
        public void Add_EmptyString_ReturnsZero()
        {
            //start with this even though StringCalculator doesn't exist yet
            StringCalculator sc = MakeCalc();

            //method doesn't exist
            int result = sc.Add("");

            //first kind of syntax
            //Assert.AreEqual(0, result);
            //second kind of syntax
            Assert.That(result, Is.EqualTo(0));
        }

        [TestCase("1",1)]
        [TestCase("2", 2)]
        public void Add_SingleNumber_ReturnsThatSingleNumber(string numbers, int expected)
        {
            StringCalculator sc = MakeCalc();

            int result = sc.Add(numbers);

            Assert.AreEqual(expected, result);
        }

        [TestCase("1,2",3)]
        [TestCase("1,3",4)]
        [TestCase("4,5",9)]
        [TestCase("14,44",58)]
        [TestCase("1,2,3", 6)]
        [TestCase("1,2,3,4,5", 15)]
        public void Add_MultipleNumbers_ReturnsTheSum(string numbers, int expected)
        {
            StringCalculator sc = MakeCalc();

            int result = sc.Add(numbers);

            Assert.AreEqual(expected, result);
        }

        [Test]
        public void Add_TwoNumbersWithLineFeedDelimeter_ReturnsTheSum()
        {
            StringCalculator sc = MakeCalc();

            int result = sc.Add("1\n2");

            Assert.AreEqual(3, result);
        }

        [TestCase("1\n3", 4)]
        [TestCase("1\n2\n3", 6)]
        [TestCase("1\n222\n3\n20", 246)]
        public void Add_MultipleNumbersWithLineFeedDelimeter_ReturnsTheSum(string numbers, int expected)
        {
            StringCalculator sc = MakeCalc();

            int result = sc.Add(numbers);

            Assert.AreEqual(expected, result);
        }

        [Test]
        public void Add_TwoNumbersWithGeneralDelimeter_ReturnsTheSum()
        {
            StringCalculator sc = MakeCalc();

            int result = sc.Add("//;\n1;2");

            Assert.AreEqual(3, result);
        }

        [TestCase("//;\n1;2", 3)]
        [TestCase("//;\n1;2;3", 6)]
        [TestCase("//;\n1;2;3;20", 26)]
        [TestCase("//x\n1x2x3x20", 26)]
        public void Add_MultipleNumbersWithGeneralDelimeter_ReturnsTheSum(string numbers, int expected)
        {
            StringCalculator sc = MakeCalc();

            int result = sc.Add(numbers);

            Assert.AreEqual(expected, result);
        }

        [Test]
        public void Add_NegativeNumber_ThrowsCorrectExceptionWithNegativeNumber()
        {
            StringCalculator sc = MakeCalc();

            Exception exception = Assert.Throws<Exception>(delegate
                                                                {
                                                                    sc.Add("-1");
                                                                });
            Assert.AreEqual("Negatives not allowed: -1", exception.Message);
        }

        [Test]
        public void Add_MultipleNegativeNumbers_ThrowsAnExceptionWithAllNegativeNumbers()
        {
            StringCalculator sc = MakeCalc();

            Exception exception = Assert.Throws<Exception>(delegate
                                                                {
                                                                    sc.Add("-1,-2");
                                                                });
            
            Assert.AreEqual("Negatives not allowed: -1, -2", exception.Message);
        }

        [TestCase("-1,-2", "-1, -2")]
        [TestCase("-1,-2,-3", "-1, -2, -3")]
        [TestCase("-1,2,-3", "-1, -3")]
        public void Add_MixedMultipleNegativeAndPositiveNumbers_ThrowsAnExceptionWithAllNegativeNumbers(string numbers, string expected)
        {
            StringCalculator sc = MakeCalc();

            Exception exception = Assert.Throws<Exception>(delegate
                                                                {
                                                                    sc.Add(numbers);
                                                                });

            Assert.AreEqual("Negatives not allowed: " + expected, exception.Message);
        }
    }

    public class StringCalculator
    {
        public int Add(string numbers)
        {
            string delimeter;
            if (numbers.Contains("//"))
            {
                delimeter = numbers.Substring(2, 1);
                numbers = numbers.Substring(4, numbers.Length-4);
                numbers = numbers.Replace(delimeter, ",");
            }
            else if (numbers.Contains("\n"))
                numbers = numbers.Replace("\n", ",");

            if (numbers.Length == 0)
                return 0;
            if (numbers.Length == 1)
                return int.Parse(numbers);

            if (numbers.Length == 2)
            {
                int i = int.Parse(numbers);
                if (i < 0)
                    throw new Exception("Negatives not allowed: " + i.ToString());
                return i;
            }

            string[] listOfNumbers = numbers.Split(',');

            string errorMesssage = "Negatives not allowed: ";
            bool showErrorMessage = false;
            foreach (var number in listOfNumbers)
            {
                int i = int.Parse(number);
                if (i < 0)
                {
                    errorMesssage += i.ToString() + ", ";
                    showErrorMessage = true;
                }
            }

            //get rid of final comma and space
            if (showErrorMessage)
            {
                errorMesssage = errorMesssage.Substring(0, errorMesssage.Length - 2);
                throw new Exception(errorMesssage);
            }

            int sumOfNumbers = 0;
            foreach (var number in listOfNumbers)
                sumOfNumbers += int.Parse(number);

            return sumOfNumbers;

        }
    }

first show at just getting tests to pass.

Started refactorugb with help from videos on: http://osherove.com/tdd-kata-1/

linq, extension methods, make more readable using methods

http://vimeo.com/27977192

| | # 
( TDD | TekPub )

From tekpub.com

Unit Tests – “.. a test of a small functional piece of code”

run in memory (not db!).. all under our control…always expect unit tests to pass

ie not integration test.. which has dependencies.

 

Creating a new blank solution (actually called it MyProduct)

image

then create a class library called MyProduct.Logic

image

downloaded Resharper.

Alt Enter to get rid of usings

 

image

setting up a separate project for UnitTests (and further down the line, integration tests).

image

installing unit via nuget console window. (Alt t n o)

Don’t need punit or the mock dlls.  So just nunit.framework.

 

tests – don’t test math forumulae.  Just logic.

Test Naming

whats being tested:  Add

scenario:  TwoNumbers

expected behaviour

eg Add_TwoNumbers_ReturnsTheSum

Test Lint – tells you if no asserts.  Logic in tests eg 1+2   Assert.AreEqual(1+2, result)

 

TestDriven.NET

Tools Options Keyboard

he uses alt R to rerun tests ( I use Alt T, and Alt D for debug)

Refactoring

refactor out constructor stuff when > 2 tests

put initialisation in setup – but this can be confusing when looking at a test way down the page.. so refactor to factory

[TestFixture]
    public class MyCalculatorTests
    {
        [Test]
        public void Add_TwoNumbers_ReturnsTheSum()
        {
            MyCalculator c = GetNewCalc();

            int result = c.Add(1, 2);

            Assert.AreEqual(3, result);
        }

        private static MyCalculator GetNewCalc()
        {
            return new MyCalculator();
        }
    }

static factory.

image

but attribute hmmm.. GetNewCalc could throw and exception.

Use Assert.Throws.

Delegates and Lambda expressions

[Test]
        //[ExpectedException(typeof(Exception))]
        public void Add_FirstParamNegative_Throw()
        {
            MyCalculator c = GetNewCalc();

            int ANY_POSITIVE = 1;

            //c.Add(-1, ANY_POSITIVE);

            //parameter is a delegate to a method here
            //but would have same problem as putting in an attribute
            //ie wouldn't know that GetNewCalc didn't fire an exception
            //any line of Code could throw an exception
            //Assert.Throws<Exception>(Code);

            //anonymous delegate or anonymous method
            //even though its in the scope on an anon method
            //it knows about c
            Assert.Throws<Exception>(delegate
                                         {
                                             c.Add(-1, ANY_POSITIVE);
                                         });

            //lambda expression - shorter delegate notation
            //method doesn't have any name.
            //after => body of method only has one line
            //Assert.Throws<Exception>(() => c.Add(-1, ANY_POSITIVE));
        }
  private void Code()
        {
            //c.Add(-1, ANY_POSITIVE);
        }

he prefers the delegate way – things more  readable than lambda

TDD and Learning new things

  • Copy
  • Why
  • Improvise..eg make own naming convention

Start with a failing test

Make test pass – make code as dumb and simple as possible.  Not generic.  Better tests.. better code coverage…how would 11 year old solve it?

Refactor – changing existing code without changing functionality

So, writing the test first for second param being negative throwing:

 

New Feature – Calculator Remembers Last Result

Doing the test first.. so can see that the field / property  c.LastResult doesn’t exist yet!

[Test]
        public void ResultMemory_CallingAdd_ResultIsSavedForLater()
        {
            MyCalculator c = GetNewCalc();
            int result = c.AddPositives(1, 2);
            Assert.AreEqual(3, c.LastResult);
        }

easiest way to make the test pass:

        //a backing field
        private int _lastResult;
        //property (not an auto property)
        public int LastResult
        {
            get { return 3; }
            set { _lastResult = value; }
        }

TestCase – parameterised

[TestCase(1,2,3)]
        public void ResultMemory_CallingAdd_ResultIsSavedForLater(int a, int b, int expected)
        {
            MyCalculator c = GetNewCalc();
            int result = c.AddPositives(a, b);
            Assert.AreEqual(expected, c.LastResult);
        }
| | # 
# Wednesday, 21 September 2011
( Code Snippets | Git | TekPub | VidPub )

Custom Membership..forms.

Don’t advocate roll own membership

ASP.NET Membership works if

  • SQL Server forever
  • Forms auth
  • Can login multiple times

OpenID

TDD/BDD do this.

  • NUnit
  • TestDriven.net

Code Snippets

To help with mundane writing code in unit tests.

Ctrl K Ctrl B

http://weblogs.asp.net/kdente/archive/2005/05/05/405843.aspx  Kevin Dentes Blogs and nunit snippets **not imported yet as wasn’t in .snippet format

Libraries\Documents\Visual Studio 2010\Code Snippets\Visual C#\My Code Snippets

Git console in VS

Tools/External menu.

image

which then appears in the Tools menu as git.  Change to &g for keyboard accelerator.

image

Feature branch in Git

Master is for finalised and deployed (?) code

git branch (to see current branches)

git checkout –b membership

.gitignore

*resharper.user

[Dd]ebug/

[Rr]elease/

build/

[Bb]in/

[Oo]bj/

*.suo

*.sln.cache

_ReSharper.*/

*.user

git add .

Global GitIgnore

http://jqr.github.com/2009/02/03/global-git-ignore.html

git config –global core.excludesfile c:/dev/Global.gitignore

Test 1 – Not Accept Email with < 6 Chars

From http://weblogs.asp.net/nunitaddin/

Alt + T  reassigned for run tests in TestDriven.Net

Alt + D run tests in debug

Code Snippet
public class TestBase {
        public void Describes(string description) {
            Console.WriteLine("-------------------------------");
            Console.WriteLine(description);
            Console.WriteLine("-------------------------------");
        }

        public void isPending() {
            Console.WriteLine(GetCaller() + " -- PENDING --");
            Assert.Inconclusive();
        }

        public string GetCaller() {
            StackTrace stack = new StackTrace();
            return stack.GetFrame(2).GetMethod().Name.Replace("_", " ");
        }
    }

So can get a bit of nice debug in output window:

image

YAGNI – writing smallest amount of code to make test pass.. weird but good.

 

Code Snippet
[TestFixture]
    public class MembershipSpecs : TestBase{
        public MembershipSpecs() {
            this.Describes("User Registration");
        }

        [Test]
        public void registration_should_not_accept_email_with_lt_6_chars() {
            var membership = new Membership();
            var result = membership.Register("test@test.com", "password", "password");
            Assert.False(result.Success);
        }
    }

and simplest possible implementation (not really, but Rob has an end in mind)

used Ctrl . in VS to make Membership class and file, and method.

Code Snippet
public class Membership {
        public dynamic Register(string email, string password, string confirm) {
            dynamic result = new ExpandoObject();
            result.Success = false;
            return result;
        }
    }

 

Code Snippet
[Test]
      public void registration_should_not_accept_email_with_lt_6_chars() {
          var result = _membership.Register("e", "password", "password");
          Assert.False(result.Success);
      }

      [Test]
      public void registration_should_not_accept_password_with_lt_6_chars() {
          var result = _membership.Register("test@test.com", "x", "x");
          Assert.False(result.Success);
      }

      [Test]
      public void registration_should_not_accept_mismatched_passwords() {
          var result = _membership.Register("test@test.com", "password1", "password2");
          Assert.False(result.Success);
      }

testing the False cases

Code Snippet
public dynamic Register(string email, string password, string confirm) {
            dynamic result = new ExpandoObject();
            result.Success = false;
            if (email.Length >= 6 && password.Length >=6 && password.Equals(confirm))
                result.Success = true;
            return result;
        }

Persist Information to DB – Massive

http://blog.wekeroad.com/helpy-stuff/and-i-shall-call-it-massive

Rails doesn’t matter to goto db..can be fast enough.

SQL CE4 in App_Data in Test project.  **This didn’t work.. am using SQL Server**

image

Seed on ID the PK.  getdate() on 3 date fields as default.

How to persist data?  Simplest possible for now is Massive.. a Dynamic ORM in 500lines or do.

https://github.com/robconery/massive

 

Test 2 – Registration Should Not Accept Duplicate Emails

Test is something like:

[Test]
        public void registration_should_not_accept_duplicate_emails() {
            var result = _membership.Register("test@test.com", "password", "password");
            var result2 = _membership.Register("test@test.com", "password", "password");
            Assert.False(result2.Success);
        }

so need persistence to test this:

Going to clean the db before each test!

Massive works by translating the properties of the anonymous object into column names:

Problem:  Couldn’t get Massive to connect to SQLServerCompact4.0 database with connection string:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>   <connectionStrings>     <add name="Membership"      connectionString="Data Source=C:\Dev\VidPub\Source\VidPub.Tests\App_Data\Membership_Test.sdf"      providerName="System.Data.SqlServerCE.4.0" />   </connectionStrings>
</configuration>

installed classic 2000 Northwind sample:

http://www.microsoft.com/download/en/confirmation.aspx?id=23654   then look in C:\SQL Server 2000 Sample Databases

http://ndc2011.macsimum.no/mp4/Day2%20Thursday/Track1%201140-1240.mp4 – Interesting talk from Norway on Data access history.

Now I can get a console App to talk to SQL Server Compact 4.0 :

string connectionString = ConfigurationManager.ConnectionStrings["southwind"].ConnectionString;

            //SqlCeConnection connection = new SqlCeConnection(@"Data Source=SouthWind.sdf");
            SqlCeConnection connection = new SqlCeConnection(connectionString);

            SqlCeCommand command = new SqlCeCommand("SELECT * FROM People", connection);
            SqlCeDataAdapter dataAdapter = new SqlCeDataAdapter(command);
            DataSet ds = new DataSet();
            dataAdapter.Fill(ds);
            Console.WriteLine(ds.GetXml());

now I need to get Massive talking to that db.

I can kind of get it working by changing the _providerName to

            var _providerName = "System.Data.SqlServerCE.4.0";

https://github.com/robconery/massive/pull/65 here is a fix by pulling from the App.config.

Getting strange errors!

Reverting to SQL Server

<configuration>
  <connectionStrings>
    <!--<add name="Membership" providerName="System.Data.SqlServerCE.4.0" connectionString="Data Source=C:\Dev\VidPub\Source\VidPub.Tests\Membership_Test.sdf" />-->
    <add name="Membership" providerName="System.Data.SqlClient" connectionString="Data Source=.\;Initial Catalog=Membership_Test;Integrated Security=SSPI;" />
  </connectionStrings>
</configuration>

and change provider name back to:

var _providerName = "System.Data.SqlClient";
and to put a unique constrant on SQL Server column: http://stackoverflow.com/questions/64981/sql-server-2005-how-create-a-unique-constraint

Code Snippets

image

testn is setup for me to produce:

 [Test]         public void MyTestMethod() {                      }
| | #