public static class StringHelper { public static bool IsCapitalized(this string str) { if(string.IsNullOrWhiteSpace(str)) { return false; } return char.IsUpper(str[0]); } } static void ExtensionMethodDemo() { Console.WriteLine("perth".IsCapitalized()); }
static void LocalMethod() { Cube(100); void Cube(int x) => Console.WriteLine($"The cube of {x} is {x * x * x}"); } static void GoToDemo() { int i = 1; startLoop: if(i<=5) { Console.WriteLine(i); i++; goto startLoop; } } deconstructor class Rectangle { public readonly float Width, Height; public Rectangle(float width,float height) { Width = width; Height = height; } public void Deconstruct(out float width,out float height) { width = Width; height = Height; } } static void Main(string[] args) { var rect = new Rectangle(3, 4); (float width, float height) = rect; Console.WriteLine($"width:{width},height:{height}"); Console.ReadLine(); } static void Main(string[] args) { var rect = new Rectangle(3, 4); var (width, height) = rect; Console.WriteLine($"width:{width},height:{height}"); Console.ReadLine(); } static void Main(string[] args) { var rect = new Rectangle(3, 4); (var width,var height) = rect; Console.WriteLine($"width:{width},height:{height}"); Console.ReadLine(); } class Product { decimal currentPrice, sharesOwned; public decimal Worth { get { return currentPrice * sharesOwned; } } public decimal Worth2 => currentPrice * sharesOwned; public decimal Worth3 { get => currentPrice * sharesOwned; set => sharesOwned = value / currentPrice; } public decimal CurrentPrice { get; set; } = 123; public int Maximum { get; } = 999;
}
private decimal x; public decimal X { get { return x; } private set { x = Math.Round(value, 2); } } Indexer class Sentence { string[] words = "The quick brown fox".Split(); public string this[int wordNum] { get { return words[wordNum]; } set { words[wordNum] = value; } } } static void Main(string[] args) { Sentence se = new Sentence(); Console.WriteLine(se[3]); se[3] = "kangaroo"; Console.WriteLine(se[3]); Console.ReadLine(); } static class StaticClass { static StaticClass() { Console.WriteLine("This is the static constructor of the static class!"); } public static DateTime DT = DateTime.Now; } Partial class,partial method. partial class PaymentForm { partial void ValidatePayment(decimal amount); public void InvokePartialMethod(decimal amount) { ValidatePayment(amount); } } partial class PaymentForm { partial void ValidatePayment(decimal amount) { if(amount>100) { Console.WriteLine("Luxury"); } else { Console.WriteLine("Ok"); } } } static void Main(string[] args) { PaymentForm pf = new PaymentForm(); pf.InvokePartialMethod(10); pf.InvokePartialMethod(101); Console.ReadLine(); }
internal class Countdown : IEnumerator { int count = 11; public object Current => count; public bool MoveNext() => count-- > 0; public void Reset() { throw new NotImplementedException(); } } static void Main(string[] args) { IEnumerator e = new Countdown(); while(e.MoveNext()) { Console.WriteLine(e.Current); } Console.ReadLine(); } [Flags] public enum BorderSides { None=0,Left=1,Right=2,Top=4,Bottom=8 } static void Main(string[] args) { BorderSides leftRight = BorderSides.Left | BorderSides.Right; if((leftRight&BorderSides.Left)!=0) { Console.WriteLine("Includes Left!"); } string formatted = leftRight.ToString(); BorderSides s = BorderSides.Left; s |= BorderSides.Right; Console.WriteLine(s == leftRight); Console.ReadLine(); } [Flags] public enum BSS { None=0,Left=1,Right=2,Top=4,Bottom=8, LeftRight=Left|Right, TopBottom=Top|Bottom, All=LeftRight|TopBottom } Nested types public class TopLevel { public class Nested { } public enum Color { Red,Blue,Tan} } static void Main(string[] args) { TopLevel.Color color = TopLevel.Color.Red; Console.WriteLine(color); Console.ReadLine(); } Generics express reusability with a "Template" that contains "placeholder" types.Generics when compared to inheritance,can increase type safety and reduce casting and boxing. public class Stack<T> { int pos; T[] data = new T[100]; public void Push(T obj) => data[pos++] = obj; public T Pop() => data[--pos]; } static void Main(string[] args) Console.ReadLine();
static void Main(string[] args) { Func<int,int,int> fc = AddXY; int result = AddXY(10, 20); Console.WriteLine(result); Console.ReadLine(); } private static int AddXY(int v1, int v2) { return v1 + v2; } delegate,eventHandler,eventargs public class Stock { string symbol; decimal priceValue; public Stock(string symbol) { this.symbol = symbol; } public event EventHandler<PriceChangedEventArgs> PriceChanged; protected virtual void OnPriceChanged(PriceChangedEventArgs e) { if(PriceChanged!=null) { PriceChanged(this, e); } } public decimal Price { get { return priceValue; } set { if(priceValue==value) { return; } OnPriceChanged(new PriceChangedEventArgs(priceValue, value)); priceValue = value; } } } public class PriceChangedEventArgs : EventArgs { public readonly decimal LastPrice, NewPrice; public PriceChangedEventArgs(decimal lastPriceValue, decimal newPriceValue) { LastPrice = lastPriceValue; NewPrice = newPriceValue; } } public delegate void EventHandler<TEventArgs>(object source, TEventArgs e) where TEventArgs : EventArgs; }
static void Main(string[] args) { Stock stk = new Stock("SMF"); stk.Price = 27.10M; stk.PriceChanged += StkPriceChanged; stk.Price = 39.99M; Console.ReadLine(); } private static void StkPriceChanged(object source, PriceChangedEventArgs e) { decimal rate = ((e.NewPrice - e.LastPrice) / e.LastPrice); Console.WriteLine($"The rate is {rate}"); if((e.NewPrice-e.LastPrice)/e.LastPrice>0.1M) { Console.WriteLine("Alert,10% price increase!"); } }
public class Stk { string symbol; decimal priceValue; public Stk(string symbolValue) { this.symbol = symbolValue; } public event EventHandler PriceChanged; protected virtual void OnPriceChanged(EventArgs e) { if(PriceChanged!=null) { PriceChanged(this, e); } } public decimal Price { get { return priceValue; } set { if(priceValue==value) { return; } OnPriceChanged(EventArgs.Empty); priceValue = value; } } } public class Stck { EventHandler priceChangedHandler; public event EventHandler PriceChanged { add { priceChangedHandler += value; } remove { priceChangedHandler -= value; } } } public interface IFoo { event EventHandler Ev; } class Foo : IFoo { EventHandler ev; public event EventHandler Ev { add { ev += value; } remove { ev -= value; } } } Lambda Expression. delegate int Math2Del(int x, int y); static void Main(string[] args) { Math2Del add = (x, y) => x + y; Console.WriteLine(add(10, 20)); Math2Del subtract = (x, y) => x - y; Console.WriteLine(subtract(10, 20)); Console.ReadLine(); } delegate void Math3Del(int x, int y); static void Main(string[] args) { Math3Del add = (x, y) => { Console.WriteLine($"{x}-{y}={x - y}"); }; add(10, 20); Console.ReadLine(); } static void Main(string[] args) { Func<int, int> sqrt = x => x * x; Console.WriteLine(sqrt(10)); Func<int, int> cube = (int x) => x * x * x; Console.WriteLine(cube(10)); Console.ReadLine(); }
static void Main(string[] args) { Func<string, string, int> totalLength = (s1, s2) => s1.Length + s2.Length; Console.WriteLine(totalLength("Hello", "Make every second count!")); Console.ReadLine(); } static void Main(string[] args) { Action<string, string> totalLength = (s1, s2) => { Console.WriteLine($"The sum length of {s1} and {s2} is {s1.Length + s2.Length}"); }; totalLength("Wonderful", "Make every second count!"); Console.ReadLine(); } static void Main(string[] args) { Action<int> cube = x => { Console.WriteLine($"The cuble of {x} is {x * x * x}"); }; cube(1000); Console.ReadLine(); } C# closure static void Main(string[] args) { Action[] actionArray = new Action[3]; for(int i=0;i<3;i++) { actionArray[i] = () => { Console.WriteLine(i*10); }; } foreach(Action act in actionArray) { act(); } Console.ReadLine(); } print 30 30 30
static void Main(string[] args) { Action[] actionArray = new Action[3]; for(int i=0;i<3;i++) { int temp = i; actionArray[i] = () => { Console.WriteLine(temp * 10); }; } foreach(Action act in actionArray) { act(); } Console.ReadLine(); } delegate int MathDel(int x); static void Main(string[] args) { MathDel cube=(int x)=>{ return x * x * x; }; Console.WriteLine(cube(10)); Console.ReadLine(); }
static void Main(string[] args) { MathDel cube = x => x * x * x; Console.WriteLine(cube(10)); Console.ReadLine(); }
finally execute the action to dispose resource static void ReadFile() { StreamReader reader = null; try { reader = File.OpenText("a.txt"); if(reader.EndOfStream) { return; } Console.WriteLine(reader.ReadToEnd()); } finally { if (reader != null) { reader.Dispose(); } } } static string ThrowException(string value) => string.IsNullOrWhiteSpace(value) ? throw new ArgumentNullException(nameof(value)) : char.ToUpper(value[0]) + value.Substring(1); static void GetEnumeratorDemo() { using(var enumerator="deer".GetEnumerator()) { while(enumerator.MoveNext()) { var element = enumerator.Current; Console.WriteLine(element); } } } If the enumerator implements IDisposable, the foreach statement When you implement IEnumerable,you must also implement IEnumerator public class Person { public string FirstName; public string LastName; public Person(string fName,string lName) { FirstName = fName; LastName = lName; } } public class People : IEnumerable { private Person[] personArrayValue; public People(Person[] pArray) { personArrayValue = new Person[pArray.Length]; for(int i=0;i<pArray.Length;i++) { personArrayValue[i] = pArray[i]; } } IEnumerator IEnumerable.GetEnumerator() { return (IEnumerator)GetEnumerator(); } public PeopleEnum GetEnumerator() { return new PeopleEnum(personArrayValue); } } //When you implement IEnumerable,you must also implement IEnumerator public class PeopleEnum : IEnumerator { public Person[] PersonArray; //Enumerators are positioned before the first element //until the first MoveNext() call. int pos = -1; public PeopleEnum(Person[] personArrayValue) { PersonArray = personArrayValue; } public bool MoveNext() { pos++; return (pos < PersonArray.Length); } public void Reset() { pos = -1; } public Person Current { get { try { return PersonArray[pos]; } catch(IndexOutOfRangeException) { throw new InvalidOperationException(); } } } object IEnumerator.Current { get { return Current; } } } static void IEnumerableDemo() { Person[] personArray = new Person[3] { new Person("Fred1", "Fu"), new Person("Fred2", "Fu"), new Person("Fred3", "Fu") }; People peopleList = new People(personArray); foreach(Person p in peopleList) { Console.WriteLine($"FirstName:{p.FirstName},LastName:{p.LastName}"); } }
succinctly static void Main(string[] args) { foreach(int fib in Fibs(10)) { Console.Write(fib+"\t"); } Console.ReadLine(); } static IEnumerable<int> Fibs(int fibCount) { for (int i = 0, prevFib = 1, curFib = 1;i<fibCount;i++) { yield return prevFib; int newFib = prevFib + curFib; prevFib = curFib; curFib = newFib; } } static void Main(string[] args) { foreach(string s in FooString()) { Console.WriteLine(s); } Console.ReadLine(); } static IEnumerable<string> FooString() { yield return "One"; yield return "Two"; yield return "Three"; }
The yield break statement indicates that the iterator block should exit early. static void Main(string[] args) { foreach(string s in YieldBreak(true)) { Console.WriteLine(s); } Console.ReadLine(); } static IEnumerable<string> YieldBreak(bool breakEarly) { yield return "One"; yield return "Two"; if(breakEarly) { yield break; } yield return "Three"; } static void Main(string[] args) { IEnumerable<int> data = Enumerable.Range(0, 100000); foreach(var i in EvenNumberOnly(data)) { Console.Write(i + "\t"); } Console.ReadLine(); } static IEnumerable<int> EvenNumberOnly(IEnumerable<int> sequence) { foreach(int x in sequence) { if((x%2)==0) { yield return x; } } } static void Main(string[] args) { IEnumerable<int> data = Enumerable.Range(0, 100000); foreach(var i in EvenNumberOnly(data)) { Console.Write(i + "\t"); } Console.ReadLine(); } static IEnumerable<int> EvenNumberOnly(IEnumerable<int> sequence) { foreach(int x in sequence) { if((x%2)==0) { yield return x; } } }
yield break
nullable type static void NullableDemo() { int? i = null; Console.WriteLine(i == null); } public struct Nullable<T> where T : struct { public T Value { get; } public bool HasValue { get; } //public T GetValueOrDefault(); //public T GetValueOrDefault(T defaultValue); } static void Main(string[] args) { Nullable<int> i = new Nullable<int>(); Console.WriteLine(!i.HasValue); Console.ReadLine(); }
C# permits the unboxing of nullable types. static void Main(string[] args) { UnboxNullableTypes(); Console.ReadLine(); } static void UnboxNullableTypes() { object o = "string"; int? x = o as int?; Console.WriteLine(x.HasValue); }
static void NullableTypesComparison() { int? x = 5; int? y = 10; bool isTrue = (x.HasValue && y.HasValue) ? (x.Value < y.Value) : false; Console.WriteLine(isTrue); }
static void NullableAdd() { int? a = null; int b = 2; int? c = a + b; Console.WriteLine(c); //c is null }
Annoymous types static void AnnoymousTypes() { var fred = new { Name = "Fred", Age = 32, Salary = 100_000_000 }; Console.WriteLine($"Name={fred.Name},Age={fred.Age},Salary={fred.Salary}"); } static void AnnoymousTypes() { string title = "architect"; var fred = new { Name = "Fred", Age = 32, Salary = 100_000_000, title }; Console.WriteLine($"Name={fred.Name},Age={fred.Age},Salary={fred.Salary},title={fred.title}"); } static void AnonymouseArray() { var dudes = new[] { new {Name="Fred",Age=32}, new {Name="Fred2",Age=33} }; foreach(var du in dudes) { Console.WriteLine($"name:{du.Name},age:{du.Age}"); } } static void TupleDemo() { var tuple = ("Fred", 33, "Architect", "CEO"); Console.WriteLine($"{tuple.Item1},{tuple.Item2},{tuple.Item3},{tuple.Item4}"); } static void UnnamedTuple() { //var is optional (string,int) fred= ("Fred", 33); Console.WriteLine($"{fred.Item1},{fred.Item2}"); } static void Main(string[] args) { var p = GetPerson(); Console.WriteLine($"{p.Item1},{p.Item2}"); Console.ReadLine(); } static (string, int) GetPerson() => ("Fred", 33); Return tuple from a method. static void NamedTuples() { var fred = (Name: "Fred", Age: 33, Title: "CEO"); Console.WriteLine($"{fred.Name},{fred.Age},{fred.Title}"); } static void Main(string[] args) { var p = GetPerson2(); Console.WriteLine($"{p.name},{p.age}"); Console.ReadLine(); } //Specify tTuple types static (string name, int age) GetPerson2() =>("Fred", 33); static void DeconstructTuple() { var fred = ("Fred", 33); (string name, int age) = fred; Console.WriteLine($"{name},{age}"); (string name, int age) fred2 = ("Fred2", 32); Console.WriteLine($"{fred2.name},{fred2.age}"); } static void LinqQueryNew() { string[] names = { "Alex", "Fred", "Jim", "James" }; var query = names.Select(x => new { Name =x, Length=x.Length }); foreach(var row in query) { Console.WriteLine(row); } } static void LinqTakeSkip() { IEnumerable<int> range = Enumerable.Range(0, 100); IEnumerable<int> takeRange = range.Take(10); foreach(var i in takeRange) { Console.Write(i+"\t"); } Console.WriteLine("\n\n\n\n"); IEnumerable<int> skipRange = range.Skip(10); foreach(var i in skipRange) { Console.Write(i+"\t"); } } static void LinqFirstLast() { IEnumerable<int> dataList = Enumerable.Range(0, 1000); Console.WriteLine(dataList.First()); Console.WriteLine(dataList.Last()); Console.WriteLine($"{dataList.First(x => x % 115 == 1)}"); Console.WriteLine(dataList.Last(x => x % 888 == 1)); Console.WriteLine(dataList.ElementAt(10)); } static void LinqMaxMinAverage() {
Linq set union,concat static void LinqSetDemo() { int[] seq1 = { 1, 2, 3 }; int[] seq2 = { 3, 4, 5 }; IEnumerable<int> concatSeq = seq1.Concat(seq2); foreach(int i in concatSeq) { Console.Write(i+"\t"); } Console.WriteLine(); IEnumerable<int> unionSeq = seq1.Union(seq2); foreach(int i in unionSeq) { Console.Write(i + "\t"); } } Linq intersect,except static void LinqInsersectExceptDemo() { int[] seq1 = { 1, 2, 3 }; int[] seq2 = { 3, 4, 5 }; IEnumerable<int> intersectSet = seq1.Intersect(seq2); foreach(int i in intersectSet) { Console.Write(i + "\t"); } Console.WriteLine(); IEnumerable<int> except1 = seq1.Except(seq2); foreach(int i in except1) { Console.Write(i+"\t"); } Console.WriteLine(); IEnumerable<int> except2 = seq2.Except(seq1); foreach(int i in except2) { Console.Write(i+"\t"); } } The extra number that we sneaked into the list after constructing the query is included in the result,because it's not until the foreach statement runs that any filtering or sorting takes place.This is called deferred or lazy evalueation. Deferred execution decouples query construction from query execution,allowing you to construct a query in several steps as well as making it possible to query a database without retrieving all the rows to the client. static void DeferedExecutingDemo() { List<int> data = new List<int> { 1 }; IEnumerable<int> query = data.Select(x => x * 10); data.Add(2); data.Add(3); foreach(var a in query) { Console.WriteLine(a); } } static void LinqWhereOrderBySelectDemo() IEnumerable<string> query2 = from n in names foreach(var a in query2) The let keyword introduces a new variable alongside the range variable. static void LetDemo() { string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" }; IEnumerable<string> query = from n in names let vowelless = Regex.Replace(n, "[aeiou]", "") where vowelless.Length>2 orderby vowelless select n+"-" +vowelless; foreach(var q in query) { Console.WriteLine(q); } IEnumerable<string> query2 =
}
static void MultipleGeneratorsDemo() { int[] numbers = { 1, 2, 3 }; string[] letters = { "a", "b" }; IEnumerable<string> query = from n in numbers from l in letters select n.ToString() + l; foreach(var q in query) { Console.WriteLine(q); } IEnumerable<string> selectMany = numbers.SelectMany (x => letters, (x, l) => (x.ToString() + l)); foreach(var a in selectMany) { Console.WriteLine(a); } string[] players = { "Tom", "Jay", "Mary" }; IEnumerable<string> compare = from n1 in players from n2 in players where n1.CompareTo(n2) < 0 orderby n1, n2 select n1 + " vs " + n2; foreach(var a in compare) { Console.WriteLine(a); } string[] fullNames = { "Anne Williams", "John Fred Smith", "Sue Green" }; IEnumerable<string> q3 = from fn in fullNames from name in fn.Split() select name + " comes from " + fn; foreach (string ne in q3) { Console.WriteLine(ne); } }
static void LinqAnnoymousTypes() { var customers = new[] { new { Id = 1, Name = "Tom" }, new { Id = 2, Name = "Dick" }, new { Id = 3, Name = "Harry" } }; var purchases = new[] { new {CID=1,Product="House"}, new {CID=2,Product="Car"}, new {CID=2,Product="Mansion"}, new {CID=4,Product="Holiday"} }; IEnumerable<string> query = from c in customers join p in purchases on c.Id equals p.CID select c.Name + " bought a " + p.Product; foreach(var q in query) { Console.WriteLine(q); } IEnumerable<string> query2 = from c in customers from p in purchases where c.Id == p.CID select c.Name + " bought a " + p.Product; foreach(var a in query2) { Console.WriteLine(a); } }
static void LinqZipDemo() { int[] nums = { 3, 5, 7 }; string[] words = { "three", "five", "seven", "ignored" }; IEnumerable<string> zip = nums.Zip(words, (n, v) => n + "=" + v); foreach(var z in zip) { Console.WriteLine(z); } }
static void LinqOrderDemo() IEnumerable<string> query2 = names.OrderBy(x => x.Length).ThenBy(x => x); static void LinqGroupDemo() { string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" }; var query = from name in names group name by name.Length; foreach(IGrouping<int,string> g in query) { Console.Write("\r\n Length= " + g.Key + ":"); foreach(string name in g) { Console.Write(" " + name); } } Console.WriteLine("\n\n\n\n\n"); var query2 = names.GroupBy(x => x.Length); foreach(IGrouping<int,string> g in query2) { Console.WriteLine("Length=" + g.Key); foreach(string name in g) { Console.WriteLine(name); } } }
static void TaskGetAwaiterDemo() { Task<int> task = ComplexcalculationAsync(); var awaiter = task.GetAwaiter(); awaiter.OnCompleted(() => { int result = awaiter.GetResult(); Console.WriteLine(result); }); } static Task<int> ComplexcalculationAsync() { return Task.Run(() => ComplexCalculation()); } static int ComplexCalculation() { double x = 2; for (int i = 1; i < 100000000; i++) { x += Math.Sqrt(x) / i; } return (int)x; }
The expression upon which you await is typically a task;however,any object with a GetAwaiter method that returns an awaitable object-implementing INotifyCompletion.OnCompleted and with an appropriately typed GetResult method and a bool IsCompleted property that tests for synchronous completion will satisfy the compiler. static void Main(string[] args) { Console.WriteLine($"Now is {DateTime.Now.ToString("yyyyMMddHHmmssffff")} Begin"); Task.Delay(5000); Console.WriteLine($"Now is {DateTime.Now.ToString("yyyyMMddHHmmssffff")} End"); Console.ReadLine(); } static async void TaskWhenAll() { await Task.WhenAll(GetIntTask(), GetIntTask()); Console.WriteLine("Done"); } static async void TaskWhenAll() { await Task.WhenAll(GetIntTask(), GetIntTask()); Console.WriteLine("Done"); } static async void FuncAsync() { await unnamed(); await NamedTaskMethod(); } static Func<Task> unnamed = async () => { await Task.Delay(2000); Console.WriteLine("Unnamed!"); }; static async Task NamedTaskMethod() { await Task.Delay(5000); Console.WriteLine("Done"); } The unsafe code,pointer. The fixed statement is required to pin a managed object such as the bitmap in the previous example. The fixed statement tells the garbage collector to pin the object and not move it around. Whithin a fixed statement,you can get a pointer to a value type an array of value types,or a string. static void Main(string[] args) { UnsafeMethod(); Console.ReadLine(); } int x; unsafe static void UnsafeMethod() { Program obj = new Program(); fixed (int* p = &obj.x) { *p = 9; } Console.WriteLine(obj.x); }
In addition to the & and * ,operators,C# also provides the C++ style ->operator which can be used on structs. struct Test { int x; unsafe static void Main() { Test test = new Test(); Test* p = &test; p->x = 9; Console.WriteLine(test.x); } }
The stackalloc keyword can help you allocate memory in a block on the stack explicitly. unsafe static void StackAllocDemo() { int* a = stackalloc int[10]; for(int i=0;i<10;i++) { Console.WriteLine(a[i]); } }
//allocate a block of memory within a struct unsafe struct UnsafeUnicodeString { public short length; public fixed byte buffer[30]; } //allocate a block of memory within a struct unsafe struct UnsafeUnicodeString { public short length; public fixed byte buffer[30]; } //keyword is also used in this example to pin the object on // the heap that contains the buffer unsafe class UnsafeClass { UnsafeUnicodeString uus; public UnsafeClass(string str) { uus.length = (short)str.Length; fixed(byte* p=uus.buffer) { for(int i=0;i<str.Length;i++) { p[i] = (byte)str[i]; Console.WriteLine(p[i]); } } } } unsafe static void UnsafeVoidDemo() { short[] a = { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 }; fixed(short* p=a) { Zap(p, a.Length * sizeof(short)); } foreach(short x in a) { Console.WriteLine(x); } } //A void pointer(void *) makes no assumptions about the type of //the underlying data and is useful for functions that deal with raw memory unsafe static void Zap(void* memory,int byteCount) { byte* b = (byte*)memory; for(int i=0;i<byteCount;i++) { *b++ = 0; } }
|
|