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
( 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
        }
| | # 
# Wednesday, 23 May 2012

[TestFixture]
    public class SimpleTypes
    {
        [Test]
        public void DisplayValues()
        {
            /*
             * Primitive types
             *
             * int =   .. System.Int32  ...signed.. pos and neg
             * uint = System.UInt32
             *
             * long = System.Int64
             * ulong = System.UInt64
             *
             * byte = System.Byte (8 bits)
             * sbyte = System.SByte (8 bits)
             *
             * short = System.Int16
             * ushort = System.UInt16
             * */
            BigInteger bigInt = new BigInteger();

            //reference type.. piece of paper with instructions
            //value type.. like writing number 5 on piece of paper

            int x = 10; //value type
            int y = x; //copy current value of x into y
            x = 20;

            x = x + 20;
            x += 20; //compound assignment
            x++; //postfix increment
            ++x; //prefix increment
            Console.WriteLine(y); //10

            //int x = 10;
            //int y = x++;  //y would be 10! x would be 11..  not nice.
        }

        [Test]
        public void stuff()
        {
            int x = 10;
            //x = x++;  //nasty x set to 10, x incremnt to 11, then assigned to 10 again
            x = x++ + ++x; //ahhh.. # will evaluate left hand side, then right
            // 10 + 12

            //BOMDAS Brackets Of Multiplication Division Addition Substraction
            Console.WriteLine(x);
        }

typing in /* will make comments keep on going!

| | # 
# 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**

| | #