Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates to the C# Koans based on experiences with ~50 students #6

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion AutoKoanRunner/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ static void Main(string[] args)
{
if (Array.TrueForAll(KoanSource.Sources, source => Directory.Exists(source.SourceFolder)) == false)
{
Console.WriteLine("The Koans were not where we expecte them to be.");
Console.WriteLine("The Koans were not where we expected them to be.");
return;
}
FileSystemWatcher[] watchers = Array.ConvertAll(
Expand Down Expand Up @@ -86,6 +86,10 @@ private static bool BuildProject(KoanSource koans)
build.StartInfo.CreateNoWindow = true;
build.Start();
build.WaitForExit();
if(build.ExitCode != 0)
{
Console.WriteLine("There was a build error. Please check your code and try again.");
}
}
return false;
}
Expand Down
36 changes: 0 additions & 36 deletions CSharp/AboutArrays.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,41 +67,5 @@ public void SlicingArrays()
Assert.Equal(new string[] { (string)FILL_ME_IN, (string)FILL_ME_IN }, array.Take(2).ToArray());
Assert.Equal(new string[] { (string)FILL_ME_IN, (string)FILL_ME_IN }, array.Skip(1).Take(2).ToArray());
}

[Koan(5)]
public void PushingAndPopping()
{
var array = new[] { 1, 2 };
Stack stack = new Stack(array);
stack.Push("last");
Assert.Equal(FILL_ME_IN, stack.ToArray());
var poppedValue = stack.Pop();
Assert.Equal(FILL_ME_IN, poppedValue);
Assert.Equal(FILL_ME_IN, stack.ToArray());
}

[Koan(6)]
public void Shifting()
{
//Shift == Remove First Element
//Unshift == Insert Element at Beginning
//C# doesn't provide this natively. You have a couple
//of options, but we'll use the LinkedList<T> to implement
var array = new[] { "Hello", "World" };
var list = new LinkedList<string>(array);

list.AddFirst("Say");
Assert.Equal(FILL_ME_IN, list.ToArray());

list.RemoveLast();
Assert.Equal(FILL_ME_IN, list.ToArray());

list.RemoveFirst();
Assert.Equal(FILL_ME_IN, list.ToArray());

list.AddAfter(list.Find("Hello"), "World");
Assert.Equal(FILL_ME_IN, list.ToArray());
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace DotNetKoans.CSharp
{
public class AboutArrayAssignment : Koan
public class AboutAssignment : Koan
{
//Parallel Assignments are a feature in Ruby which allow one
//to set multiple variables at once using an array syntax. e.g.
Expand Down
8 changes: 4 additions & 4 deletions CSharp/AboutControlStatements.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,15 @@ public void IsOperators()
bool isAboutControlStatements = false;
bool isAboutMethods = false;

var myType = this;
var myInstance = this;

if (myType is Koan)
if (myInstance is Koan)
isKoan = true;

if (myType is AboutControlStatements)
if (myInstance is AboutControlStatements)
isAboutControlStatements = true;

if (myType is AboutMethods)
if (myInstance is AboutMethods)
isAboutMethods = true;

Assert.Equal(FILL_ME_IN, isKoan);
Expand Down
26 changes: 15 additions & 11 deletions CSharp/AboutDelegates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class AboutDelegates : Koan
{
//A delegate is a user defined type just like a class.
//A delegate lets you reference methods with the same signature and return type.
//Once you have the reference to the method, pass them as paramters or call it via the delegate.
//Once you have the reference to the method, pass them as parameters or call it via the delegate.
//In other languages this is known as functions as first class citizens.

//Here is a delegate declaration
Expand All @@ -31,9 +31,10 @@ public static int Subtract(int lhs, int rhs)
[Koan(1)]
public void DelegatesAreReferenceTypes()
{
//If you don't initialize a delegate it will be a null value, just as any other refrence type.
//If you don't initialize a delegate it will be a null value, just as any other reference type.
BinaryOp op;
Assert.Null(FILL_ME_IN);
// At this point op is so null that the following line won't even compile:
// Assert.Null(op);
}
[Koan(2)]
public void DelegatesCanBeInstantiated()
Expand Down Expand Up @@ -62,22 +63,22 @@ public void MethodsCalledViaDelegate()
BinaryOp op = math.Add;
Assert.Equal(FILL_ME_IN, op(3,3));
}
private void PassMeTheDelegate(BinaryOp passed)
private int PassMeTheDelegate(BinaryOp passed)
{
Assert.Equal(FILL_ME_IN, passed(3,3));
return passed(3, 3);
}
[Koan(6)]
public void DelegatesCanBePassed()
{
MyMath math = new MyMath();
BinaryOp op = math.Add;
PassMeTheDelegate(op);
Assert.Equal(FILL_ME_IN, PassMeTheDelegate(op));
}
[Koan(7)]
public void MethodCanBePassedDirectly()
{
MyMath math = new MyMath();
PassMeTheDelegate(math.Add);
Assert.Equal(FILL_ME_IN, PassMeTheDelegate(math.Add));
}
[Koan(8)]
public void DelegatesAreImmutable()
Expand Down Expand Up @@ -169,7 +170,7 @@ public void BuiltInActionDelegateTakesString()
[Koan(14)]
public void BuiltInActionDelegateIsOverloaded()
{
//Action is an overloaded delegate so it can take more than one paramter
//Action is an overloaded delegate so it can take more than one parameter
Action<int, string> a = AssertAddEqualsFourtyTwo;
a(12, (string)FILL_ME_IN);
}
Expand Down Expand Up @@ -270,8 +271,8 @@ public void FuncWithNoParameters()
// public delegate TResult Func<T, TResult>(T arg);
//Is very similar to the Action<> delegate. However, Func<> does not require any parameters, while does require returns a value.
//The last type parameter specifies the return type. If you only specify a single
//type, Func<int>, then the method takes no paramters and returns an int.
//If you specify more than one parameter, then you are specifying the paramter types as well.
//type, Func<int>, then the method takes no parameters and returns an int.
//If you specify more than one parameter, then you are specifying the parameter types as well.

Func<string> d = FirstMonth;
Assert.Equal(FILL_ME_IN, d());
Expand Down Expand Up @@ -308,7 +309,10 @@ public void SortingWithComparison()
//You could make classes sortable by implementing IComparable or IComparer. But the Comparison<> delegate makes it easier
// public delegate int Comparison<T>(T x, T y);
//All you need is a method which takes two of the same type and returns -1, 0, or 1 depending upon what order they should go in.
var cars = new[] { new Car("Alfa Romero", "GTV-6", 1986), new Car("BMC", "Mini", 1959) };
var cars = new[] {
new Car("BMC", "Mini", 1959),
new Car("Alfa Romero", "GTV-6", 1986),
new Car("Dodge", "Ram", 2011) };
Comparison<Car> by = SortByModel;
Array.Sort(cars, by);

Expand Down
111 changes: 79 additions & 32 deletions CSharp/AboutGenericContainers.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Xunit;
using System.Collections;
using System.Linq;

namespace DotNetKoans.CSharp
{
Expand Down Expand Up @@ -129,7 +130,7 @@ public void BeyondTheLimits()
Assert.Throws(typeof(FillMeIn), delegate() { int x = list[3]; });
}
[Koan(12)]
public void ConvertingToFixedSize()
public void ConvertingToFixedSizeArray()
{
List<int> list = new List<int> { 1, 2, 3 };
Assert.Equal(FILL_ME_IN, list.ToArray());
Expand All @@ -148,8 +149,21 @@ public void RemovingItems()
list.Remove(2);
Assert.Equal(FILL_ME_IN, list.ToArray());
}

[Koan(15)]
public void StackPushPop()
public void BasicStackPushingAndPopping()
{
var array = new[] { 1, 2 };
Stack stack = new Stack(array);
stack.Push("last");
Assert.Equal(FILL_ME_IN, stack.ToArray());
var poppedValue = stack.Pop();
Assert.Equal(FILL_ME_IN, poppedValue);
Assert.Equal(FILL_ME_IN, stack.ToArray());
}

[Koan(16)]
public void GenericStackPushPop()
{
var stack = new Stack<int>();
Assert.Equal(FILL_ME_IN, stack.Count);
Expand All @@ -162,7 +176,7 @@ public void StackPushPop()

Assert.Equal(FILL_ME_IN, stack.Count);
}
[Koan(16)]
[Koan(17)]
public void StackOrder()
{
var stack = new Stack<int>();
Expand All @@ -172,7 +186,7 @@ public void StackOrder()

Assert.Equal(FILL_ME_IN, stack.ToArray());
}
[Koan(17)]
[Koan(18)]
public void PeekingIntoAQueue()
{
Queue<string> queue = new Queue<string>();
Expand All @@ -181,7 +195,7 @@ public void PeekingIntoAQueue()
queue.Enqueue("two");
Assert.Equal(FILL_ME_IN, queue.Peek());
}
[Koan(18)]
[Koan(19)]
public void RemovingItemsFromTheQueue()
{
Queue<string> queue = new Queue<string>();
Expand All @@ -190,7 +204,29 @@ public void RemovingItemsFromTheQueue()
Assert.Equal(FILL_ME_IN, queue.Dequeue());
Assert.Equal(FILL_ME_IN, queue.Count);
}
[Koan(19)]
[Koan(20)]
public void Shifting()
{
//Shift == Remove First Element
//Unshift == Insert Element at Beginning
//C# doesn't provide this natively. You have a couple
//of options, but we'll use the LinkedList<T> to implement
var array = new[] { "Hello", "World" };
var list = new LinkedList<string>(array);

list.AddFirst("Say");
Assert.Equal(FILL_ME_IN, list.ToArray());

list.RemoveLast();
Assert.Equal(FILL_ME_IN, list.ToArray());

list.RemoveFirst();
Assert.Equal(FILL_ME_IN, list.ToArray());

list.AddAfter(list.Find("Hello"), "World");
Assert.Equal(FILL_ME_IN, list.ToArray());
}
[Koan(21)]
public void AddingToADictionary()
{
//Dictionary<TKey, TValue> is .Net's key value store. The key and the value do not need to be the same types.
Expand All @@ -199,7 +235,7 @@ public void AddingToADictionary()
dictionary[1] = "one";
Assert.Equal(FILL_ME_IN, dictionary.Count);
}
[Koan(20)]
[Koan(22)]
public void AccessingData()
{
Dictionary<string,string> dictionary = new Dictionary<string,string>();
Expand All @@ -209,14 +245,14 @@ public void AccessingData()
Assert.Equal(FILL_ME_IN, dictionary["one"]);
Assert.Equal(FILL_ME_IN, dictionary["two"]);
}
[Koan(21)]
[Koan(23)]
public void AccessingDataNotAdded()
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary["one"] = "uno";
Assert.Throws(typeof(FillMeIn), delegate() { string s = dictionary["two"]; });
}
[Koan(22)]
[Koan(24)]
public void CatchingMissingData()
{
//To deal with the throw when data is not there, you could wrap the data access in a try/catch block...
Expand All @@ -233,7 +269,26 @@ public void CatchingMissingData()
}
Assert.Equal(FILL_ME_IN, result);
}
[Koan(23)]
[Koan(25)]
public void KeyExists()
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary["one"] = "uno";
Assert.Equal(FILL_ME_IN, dictionary.ContainsKey("one"));
Assert.Equal(FILL_ME_IN, dictionary.ContainsKey("two"));
}

[Koan(26)]
public void ValueExists()
{
// This should have been at the top
Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary["one"] = "uno";
Assert.Equal(FILL_ME_IN, dictionary.ContainsValue("uno"));
Assert.Equal(FILL_ME_IN, dictionary.ContainsValue("dos"));
}

[Koan(27)]
public void PreCheckForMissingData()
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
Expand All @@ -249,27 +304,34 @@ public void PreCheckForMissingData()
}
Assert.Equal(FILL_ME_IN, result);
}
[Koan(24)]

[Koan(28)]
public void TryGetValueForMissingData()
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary["one"] = "uno";
string result;
if (!dictionary.TryGetValue("one", out result))
{
result = "is the lonliest number";
}
Assert.Equal(FILL_ME_IN, result);

if (!dictionary.TryGetValue("two", out result))
{
result = "dos";
}
Assert.Equal(FILL_ME_IN, result);
}
[Koan(25)]
[Koan(29)]
public void InitializingADictionary()
{
//Although it is not common, you can initialize a dictionary...
var dictionary = new Dictionary<string, string> { { "one", "uno" }, { "two", "dos" } };
Assert.Equal(FILL_ME_IN, dictionary["one"]);
Assert.Equal(FILL_ME_IN, dictionary["two"]);
}
[Koan(26)]
[Koan(30)]
public void ModifyingData()
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
Expand All @@ -278,24 +340,9 @@ public void ModifyingData()
dictionary["one"] = "ein";
Assert.Equal(FILL_ME_IN, dictionary["one"]);
}
[Koan(27)]
public void KeyExists()
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary["one"] = "uno";
Assert.Equal(FILL_ME_IN, dictionary.ContainsKey("one"));
Assert.Equal(FILL_ME_IN, dictionary.ContainsKey("two"));
}
[Koan(28)]
public void ValueExists()
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary["one"] = "uno";
Assert.Equal(FILL_ME_IN, dictionary.ContainsValue("uno"));
Assert.Equal(FILL_ME_IN, dictionary.ContainsValue("dos"));
}
[Koan(29)]
public void f()

[Koan(31)]
public void ForEachKeyValuePair()
{
Dictionary<string, int> one = new Dictionary<string, int>();
one["jim"] = 53;
Expand Down
Loading