[dotnet] Add dotnet projects and examples
+ Sitemap generator I created while learning the dispose pattern + Testing project for learning general C#
This commit is contained in:
70
dotnet/testing/KlipsLibrary/Animal.cs
Normal file
70
dotnet/testing/KlipsLibrary/Animal.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System.Collections;
|
||||
using KlipsLibrary;
|
||||
namespace KlipsLibrary;
|
||||
public class Solution {
|
||||
public int NumUniqueEmails(string[] emails)
|
||||
{
|
||||
HashSet<string> sent = new();
|
||||
foreach (var email in emails)
|
||||
{
|
||||
var domain = email.Substring(email.IndexOf("@"), email.Length);
|
||||
var to = email.Substring(0, email.IndexOf("@"));
|
||||
if (to.Contains(".")) to = to.Replace(".", "");
|
||||
to = to.Remove(to.IndexOf("+"));
|
||||
Console.Write("{0} at {1}", to, domain);
|
||||
sent.Add(to + "@" + domain);
|
||||
}
|
||||
|
||||
return sent.Count;
|
||||
}
|
||||
}
|
||||
public abstract class Animal
|
||||
{
|
||||
public Animal(string n, string p)
|
||||
{
|
||||
this.Name = n;
|
||||
this.Phrase = p;
|
||||
}
|
||||
|
||||
public abstract void Speak();
|
||||
|
||||
private string name;
|
||||
public string Name { get; set; }
|
||||
private string phrase;
|
||||
public string Phrase { get; set; }
|
||||
}
|
||||
|
||||
public class Dog : Animal
|
||||
{
|
||||
public Dog(string n, string p) : base(n, p) { }
|
||||
|
||||
public override void Speak()
|
||||
{
|
||||
Console.WriteLine("{0} (Dog): {1}", Name, Phrase);
|
||||
}
|
||||
}
|
||||
|
||||
public class Human : Animal
|
||||
{
|
||||
public Human(string n, string p) : base(n, p) { }
|
||||
|
||||
public override void Speak()
|
||||
{
|
||||
Console.WriteLine("{0} (Human): {1}", Name, Phrase);
|
||||
}
|
||||
}
|
||||
|
||||
public class Teacher : Human, IComparable, ICloneable
|
||||
{
|
||||
public Teacher(string n, string p) : base(n, p) { }
|
||||
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
74
dotnet/testing/KlipsLibrary/Bag.cs
Normal file
74
dotnet/testing/KlipsLibrary/Bag.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
namespace KlipsLibrary;
|
||||
|
||||
public struct Item : IEquatable<Item>
|
||||
{
|
||||
public Item(double v, int q, string name)
|
||||
{
|
||||
Value = v;
|
||||
Qty = q;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public Item(double v, string name)
|
||||
{
|
||||
Value = v;
|
||||
Qty = 1;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public double Value { get; set; }
|
||||
public int Qty { get; set; }
|
||||
|
||||
public static bool operator ==(Item a, Item b)
|
||||
{
|
||||
if (((object)a) == null || ((object)b) == null) return Object.Equals(a, b);
|
||||
return a.Equals(b);
|
||||
}
|
||||
|
||||
public static bool operator !=(Item a, Item b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
public bool Equals(Item other)
|
||||
{
|
||||
return Name == other.Name && Value == other.Value;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is Item other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(Name, Value);
|
||||
}
|
||||
}
|
||||
|
||||
public class Bag
|
||||
{
|
||||
public Bag()
|
||||
{
|
||||
contents = new List<Item>();
|
||||
maxCarry = 10;
|
||||
}
|
||||
private List<Item> contents;
|
||||
private int maxCarry;
|
||||
|
||||
public bool AddItem(Item i)
|
||||
{
|
||||
if (contents.Count >= maxCarry) return false;
|
||||
contents.Add(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
public Item? TakeItem(Item i)
|
||||
{
|
||||
var found = contents.Find((Item inBag) => inBag == i);
|
||||
if (found == default(Item)) return null;
|
||||
contents.Remove(found);
|
||||
return found;
|
||||
}
|
||||
}
|
||||
19
dotnet/testing/KlipsLibrary/Fruit.cs
Normal file
19
dotnet/testing/KlipsLibrary/Fruit.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace KlipsLibrary;
|
||||
|
||||
public class Fruit
|
||||
{
|
||||
public Fruit()
|
||||
{
|
||||
Name = "Default";
|
||||
}
|
||||
|
||||
public Fruit(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
public class Fruits : Collection<Fruit> { }
|
||||
75
dotnet/testing/KlipsLibrary/InitOrder.cs
Normal file
75
dotnet/testing/KlipsLibrary/InitOrder.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
namespace KlipsLibrary;
|
||||
|
||||
public class A
|
||||
{
|
||||
public A()
|
||||
{
|
||||
Console.WriteLine("A default constructor was called");
|
||||
Val = 0;
|
||||
}
|
||||
public A(int v)
|
||||
{
|
||||
Console.WriteLine("A parameterized constructor was called");
|
||||
Val = v;
|
||||
}
|
||||
private int val;
|
||||
public int Val
|
||||
{
|
||||
// No setter; We can only initialize on construction
|
||||
init
|
||||
{
|
||||
Console.WriteLine($"A.val was initialized: {val}");
|
||||
val = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class B : A
|
||||
{
|
||||
public B()
|
||||
{
|
||||
Console.WriteLine("B default constructor was called");
|
||||
BVal = 0;
|
||||
}
|
||||
public B(int bv)
|
||||
{
|
||||
Console.WriteLine("B parameterized constructor was called");
|
||||
BVal = bv;
|
||||
}
|
||||
|
||||
private int bVal;
|
||||
|
||||
public int BVal
|
||||
{
|
||||
init
|
||||
{
|
||||
bVal = value;
|
||||
Console.WriteLine($"B.bVal was initialized: {bVal}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class C : B
|
||||
{
|
||||
public C()
|
||||
{
|
||||
Console.WriteLine("C default constructor was called");
|
||||
CVal = 0;
|
||||
}
|
||||
public C(int cv)
|
||||
{
|
||||
Console.WriteLine("C parameterized constructor was called");
|
||||
CVal = cv;
|
||||
}
|
||||
|
||||
private int cVal;
|
||||
|
||||
public int CVal
|
||||
{
|
||||
init
|
||||
{
|
||||
cVal = value;
|
||||
Console.WriteLine($"C.cVal was initialized: {cVal}");
|
||||
}
|
||||
}
|
||||
}
|
||||
281
dotnet/testing/KlipsLibrary/Klips.cs
Normal file
281
dotnet/testing/KlipsLibrary/Klips.cs
Normal file
@@ -0,0 +1,281 @@
|
||||
using System.Collections;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace KlipsLibrary;
|
||||
|
||||
public class Klips
|
||||
{
|
||||
public static void SayHello()
|
||||
{
|
||||
Console.WriteLine("Hello, C# library!");
|
||||
}
|
||||
|
||||
public static void TestInput()
|
||||
{
|
||||
string formattingString = "Captured {0} input: {1}\n";
|
||||
|
||||
Console.Write("\nInput a character, then press enter: ");
|
||||
int ascii = Console.Read();
|
||||
char ch = Convert.ToChar(ascii);
|
||||
Console.Write(formattingString, "character", ch);
|
||||
Console.ReadLine(); // Discard any left over input
|
||||
|
||||
Console.Write("\nPress a key: ");
|
||||
ConsoleKeyInfo key = Console.ReadKey();
|
||||
Console.Write("\n" + formattingString, "key", key.KeyChar);
|
||||
|
||||
Console.Write("\nEnter a line: ");
|
||||
string? line = Console.ReadLine();
|
||||
Console.Write(formattingString, "line", line);
|
||||
}
|
||||
|
||||
public static void PrintEnum<T>(IEnumerable<T> obj)
|
||||
{
|
||||
foreach (var i in obj)
|
||||
{
|
||||
Console.Write("{0}, ", i);
|
||||
}
|
||||
}
|
||||
|
||||
public static void PrintInfo<T>(IEnumerable<T> c)
|
||||
{
|
||||
Console.WriteLine("Type: {0}", c.GetType().ToString());
|
||||
}
|
||||
|
||||
public static void Print<T>(IEnumerable<T> obj)
|
||||
{
|
||||
Console.WriteLine();
|
||||
PrintInfo(obj);
|
||||
PrintEnum(obj);
|
||||
}
|
||||
|
||||
// Doesn't work because we can't resolve passed object name
|
||||
// + Limited to parameter object name; ref causes errors
|
||||
public static void PrintName<T>(T obj)
|
||||
{
|
||||
Expression<Func<object>> expression = () => obj!;
|
||||
string name = ((expression.Body as MemberExpression)!).Member.Name;
|
||||
Console.WriteLine("{0}", name);
|
||||
}
|
||||
|
||||
public static void MakeGarbage(int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var v = new Version();
|
||||
}
|
||||
}
|
||||
|
||||
public static void TestContainers()
|
||||
{
|
||||
int[] test = { 1, 2, 3, 4, 5 };
|
||||
Klips.Print(test);
|
||||
|
||||
var arr = new int[5];
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
arr[i-1] = i;
|
||||
}
|
||||
Klips.Print(arr);
|
||||
|
||||
var list = new List<int>();
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
list.Add(i);
|
||||
}
|
||||
Klips.Print(list);
|
||||
|
||||
list = list.Concat(arr).ToList();
|
||||
Klips.Print(list);
|
||||
|
||||
list.Sort();
|
||||
Klips.Print(list);
|
||||
|
||||
var dict = new Dictionary<int, string>()
|
||||
{
|
||||
[4] = "four",
|
||||
[2] = "two",
|
||||
[1] = "one",
|
||||
[3] = "three",
|
||||
[5] = "five",
|
||||
};
|
||||
Klips.Print(dict);
|
||||
for (int i = 1; i <= 5; i++)
|
||||
{
|
||||
Console.Write("\n{0}", dict[i]);
|
||||
}
|
||||
|
||||
var sortedDict = new SortedDictionary<int, string>(dict);
|
||||
Klips.Print(sortedDict);
|
||||
|
||||
var hashset = new HashSet<int>{3, 1, 4, 2};
|
||||
Klips.Print(hashset);
|
||||
|
||||
var sortedSet = new SortedSet<int>(hashset);
|
||||
Klips.Print(sortedSet);
|
||||
|
||||
var sortedList = new SortedList(sortedDict);
|
||||
Console.WriteLine("Type: {0}", sortedList.GetType().ToString());
|
||||
foreach (DictionaryEntry item in sortedList)
|
||||
{
|
||||
Console.WriteLine("Key: {0} Value: {1}", item.Key.ToString(), item.Value);
|
||||
}
|
||||
// Klips.Print(sortedList);
|
||||
|
||||
var q = new Queue<string>(dict.Values);
|
||||
Klips.Print(q);
|
||||
|
||||
var llist = new LinkedList<int>(dict.Keys);
|
||||
Klips.Print(llist);
|
||||
|
||||
}
|
||||
|
||||
public static void TestGC()
|
||||
{
|
||||
Klips.MakeGarbage(1000000);
|
||||
// GC.Collect();
|
||||
Console.Write("\nHeap memory: {0}\nAllocated heap memory: {1}",
|
||||
GC.GetGCMemoryInfo().HeapSizeBytes.ToString(), GC.GetTotalMemory(false).ToString());
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
Console.Write("\nGeneration {0} collection count: {1}", i, GC.CollectionCount(i).ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void TestStrings()
|
||||
{
|
||||
Console.Write("\n\nWhat time is it?\n{0}", DateTime.Now.ToString());
|
||||
|
||||
var lit = @"
|
||||
hi
|
||||
how
|
||||
""are"" you? \this\is\a\literal
|
||||
";
|
||||
Console.WriteLine(lit);
|
||||
|
||||
string[] @foreach = {@"\this\is\new\a\test\n", "Not verbatim\nBut still literal"};
|
||||
foreach (string s in @foreach)
|
||||
{
|
||||
Console.WriteLine(@s);
|
||||
}
|
||||
|
||||
string a = "This is my string!";
|
||||
Console.WriteLine($"This is my rifle; {a, 30}");
|
||||
Console.WriteLine($"This is {{my}} rifle; {a, -30}");
|
||||
var b = $"This {{is}} my rifle; {a}";
|
||||
Console.WriteLine(b);
|
||||
Console.WriteLine($"Conditional formatting result: {(b.Length == 0 ? "Empty" : "Not empty")}");
|
||||
var pi = Math.PI;
|
||||
Console.WriteLine($"{pi:F3}, {pi:F10}, {DateTime.Now:d}, {DateTime.Now:f}, {DateTime.Now.ToLocalTime():h:mm:ss tt zz}");
|
||||
|
||||
string fmt = "This is pi: {0}\nThis is the date: {1}\nThis is also pi: {0:F6}";
|
||||
Console.WriteLine(fmt, Math.PI, DateTime.Now);
|
||||
}
|
||||
|
||||
public static void TestLambdas()
|
||||
{
|
||||
// Both of these lambdas are of the same type; Func<string, int> where int is the value returned
|
||||
var getLen = (string s) => s.Length;
|
||||
Func<string, int> funcLen = (string s) => s.Length;
|
||||
Console.WriteLine("Length: {0}", getLen("Hello").ToString());
|
||||
Console.WriteLine("Length: {0}", funcLen("Hello").ToString());
|
||||
|
||||
var isEqual = (string a, string b) => a == b;
|
||||
Console.WriteLine(isEqual("Test", "Test"));
|
||||
Func<string, string, bool> funcIsEqual = (string a, string b) => a == b;
|
||||
Console.WriteLine(funcIsEqual("Test", "Test"));
|
||||
|
||||
// These two lamdas are both of type Action<string>, as they do not return a result
|
||||
var statement = (string s) =>
|
||||
{
|
||||
var arr = s.ToCharArray();
|
||||
Array.Reverse(arr);
|
||||
Console.WriteLine($"\"{s}\" reversed: {new string(arr)}");
|
||||
};
|
||||
Action<string> actionReverse = (string s) =>
|
||||
{
|
||||
var arr = s.ToCharArray();
|
||||
Array.Reverse(arr);
|
||||
Console.WriteLine($"\"{s}\" reversed: {new string(arr)}");
|
||||
};
|
||||
|
||||
// This lamda is a Func<string, string> as it take a string parameter and returns a string as a result
|
||||
Func<string, string> revString = (string s) =>
|
||||
{
|
||||
var revArr = s.ToCharArray();
|
||||
Array.Reverse(revArr);
|
||||
return new string(revArr);
|
||||
};
|
||||
string testS = "Racecar";
|
||||
Console.WriteLine($"{testS} reversed: {revString(testS)}");
|
||||
|
||||
statement("Test");
|
||||
}
|
||||
|
||||
public static void TestShape()
|
||||
{
|
||||
var shape = new Square();
|
||||
shape.Print();
|
||||
var shapeRef = shape;
|
||||
shapeRef.Height = 20;
|
||||
shape.Print();
|
||||
|
||||
var box = new List<Shape>();
|
||||
box.Add(new Shape(5, 5));
|
||||
box.Add(new Square());
|
||||
box.Last().Width = 8; // Access the last element we added to the List, set its width to 8
|
||||
box.Add(new Cube());
|
||||
box.Add(new Rectangle());
|
||||
box.Add(new Rect());
|
||||
// Use a lambda to find a Cube, get a reference to it; If we found a Cube, set its depth to 5
|
||||
if (box.Find((Shape s) => s.GetType() == typeof(Cube)) is Cube cubeRef) cubeRef.Depth = 5;
|
||||
foreach (var s in box) s.Print(); // Print all the Shapes
|
||||
|
||||
var cub = new Cube();
|
||||
var sqr = cub as Square;
|
||||
if (sqr != null) sqr.Print();
|
||||
|
||||
Console.WriteLine("Testing upcast");
|
||||
var c = new Cube();
|
||||
c.Print();
|
||||
if (c is Square cubeSquare)
|
||||
{
|
||||
// Why is Shape's Print() not called?; cubeShape.Print calls Square.Print() instead
|
||||
var cubeShape = cubeSquare as Shape;
|
||||
if (cubeShape != null) cubeShape.Print();
|
||||
}
|
||||
}
|
||||
|
||||
public static void TestBag()
|
||||
{
|
||||
var bag = new Bag();
|
||||
Item wrench = new Item(1.5, 1, "wrench"); // Create a wrench using Item ctor
|
||||
var spanner = wrench; // Copy wrench to a new item
|
||||
spanner.Name = "spanner";
|
||||
spanner.Value = 5.0;
|
||||
spanner.Qty = 2;
|
||||
Item socket = new Item(2.5, 5, "socket"); // Create a new item using ctor
|
||||
bag.AddItem(wrench);
|
||||
bag.AddItem(spanner);
|
||||
bag.AddItem(socket);
|
||||
Item? bagSpanner = bag.TakeItem(spanner);
|
||||
Console.WriteLine(Object.ReferenceEquals(bagSpanner, spanner));
|
||||
Item? noSpanner = bag.TakeItem(spanner);
|
||||
Console.WriteLine(noSpanner == null);
|
||||
}
|
||||
|
||||
public static void TestFruits()
|
||||
{
|
||||
Fruits fruits = new Fruits() { new Fruit(), new Fruit("Apple"), new Fruit("Orange")};
|
||||
foreach (Fruit f in fruits)
|
||||
{
|
||||
Console.WriteLine(f.Name);
|
||||
}
|
||||
}
|
||||
|
||||
public static void TestInitOrder()
|
||||
{
|
||||
var aClass = new C(5) {CVal = 10};
|
||||
}
|
||||
|
||||
}
|
||||
9
dotnet/testing/KlipsLibrary/KlipsLibrary.csproj
Normal file
9
dotnet/testing/KlipsLibrary/KlipsLibrary.csproj
Normal file
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
98
dotnet/testing/KlipsLibrary/Shape.cs
Normal file
98
dotnet/testing/KlipsLibrary/Shape.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
namespace KlipsLibrary;
|
||||
|
||||
public class Shape
|
||||
{
|
||||
public Shape(int y, int x)
|
||||
{
|
||||
Y = y;
|
||||
X = x;
|
||||
Name = this.ToString();
|
||||
}
|
||||
|
||||
public Shape()
|
||||
{
|
||||
X = 0;
|
||||
Y = 0;
|
||||
Name = this.ToString();
|
||||
}
|
||||
|
||||
// Shape position; Private setter, public getter
|
||||
public int X { get; private set; }
|
||||
public int Y { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
|
||||
// Auto-implemented properties may use a default value initializer
|
||||
public virtual int Width { get; set; } = 1;
|
||||
public virtual int Height { get; set; } = 2;
|
||||
|
||||
public virtual void Print()
|
||||
{
|
||||
Console.WriteLine($"{Name} WxH is {Width}x{Height} at position ({X},{Y})");
|
||||
}
|
||||
}
|
||||
|
||||
public class Square : Shape
|
||||
{
|
||||
// Set default value on encapsulated value for non auto-implemented properties
|
||||
private int width = 10;
|
||||
private int height = 10;
|
||||
|
||||
// We can override properties just as we can functions
|
||||
// + Height and Width properties can no longer set default values
|
||||
public override int Height
|
||||
{
|
||||
// Can use expressions for getters / setters
|
||||
get => height;
|
||||
set => width = height = value;
|
||||
}
|
||||
|
||||
public override int Width
|
||||
{
|
||||
get => width;
|
||||
set
|
||||
{
|
||||
// Same setter as Height, just within a block of statements
|
||||
width = value;
|
||||
height = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Print()
|
||||
{
|
||||
Console.WriteLine("Printing Square info...");
|
||||
base.Print(); // Will use Square's getter / setter to print private int width, height
|
||||
}
|
||||
}
|
||||
|
||||
public class Cube : Square
|
||||
{
|
||||
// Add new properties or encapsulated values as needed
|
||||
private int depth = 10;
|
||||
public int Depth
|
||||
{
|
||||
get => depth;
|
||||
set => depth = value;
|
||||
}
|
||||
// Implement a `new` Print() function which acts as a new stand-alone implementaton
|
||||
public new void Print()
|
||||
{
|
||||
Console.WriteLine("Printing Cube info...");
|
||||
Console.WriteLine($"{Name} WxHxD is {Width}x{Height}x{Depth} at position ({X},{Y})");
|
||||
}
|
||||
}
|
||||
|
||||
public class Rectangle : Shape
|
||||
{
|
||||
// Classes that inherit from Rectangle can not override Print
|
||||
public sealed override void Print()
|
||||
{
|
||||
Console.WriteLine("Printing sealed Rectangle info...");
|
||||
base.Print();
|
||||
}
|
||||
}
|
||||
|
||||
public class Rect : Rectangle
|
||||
{
|
||||
// Rect can't override Print(), since its base class declared it as `sealed`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user