// Declare the generic class. public class GenericList<T> { public void Add(T input) { } } class TestGenericList { private class ExampleClass { } static void Main() { // Declare a list of type int. GenericList<int> list1 = new GenericList<int>(); list1.Add(1);
// Declare a list of type string. GenericList<string> list2 = new GenericList<string>(); list2.Add("");
// Declare a list of type ExampleClass. GenericList<ExampleClass> list3 = new GenericList<ExampleClass>(); list3.Add(new ExampleClass()); } }
// Assignment compatibility. string str = "test"; // An object of a more derived type is assigned to an object of a less derived type. object obj = str;
// Covariance. IEnumerable<string> strings = new List<string>(); // An object that is instantiated with a more derived type argument // is assigned to an object instantiated with a less derived type argument. // Assignment compatibility is preserved. IEnumerable<object> objects = strings;
// Contravariance. // Assume that the following method is in the class: // static void SetObject(object o) { } Action<object> actObject = SetObject; // An object that is instantiated with a less derived type argument // is assigned to an object instantiated with a more derived type argument. // Assignment compatibility is reversed. Action<string> actString = actObject;
// This class is mutable. Its data can be modified from // outside the class. class Customer { // Auto-implemented properties for trivial get and set public double TotalPurchases { get; set; } public string Name { get; set; } public int CustomerID { get; set; }
// Constructor public Customer(double purchases, string name, int ID) { TotalPurchases = purchases; Name = name; CustomerID = ID; }
// Methods public string GetContactInfo() { return "ContactInfo"; } public string GetTransactionHistory() { return "History"; }
// .. Additional methods, events, etc. }
class Program { static void Main() { // Intialize a new object. Customer cust1 = new Customer(4987.63, "Northwind", 90108);
// Modify a property. cust1.TotalPurchases += 499.99; } }
匿名类型
1 2 3 4 5
var v = new { Amount = 108, Message = "Hello" };
// Rest the mouse pointer over v.Amount and v.Message in the following // statement to verify that their inferred types are int and n . Console.WriteLine(v.Amount + v.Message);
查询表达式(LINQ)
LINQ允许你可以像写SQL一样写C#代码,像这样:
1 2 3 4 5 6 7
from p in persons where p.Age > 18 && p.IsBeatiful select new { p.WeChatId, p.PhoneNumber }
// Interfaces can be extended, too: Console.WriteLine ("Seattle".First()); // S }
public static class StringHelper { public static bool IsCapitalized (this string s) { if (string.IsNullOrEmpty(s)) return false; return char.IsUpper (s[0]); }
public static T First<T> (this IEnumerable<T> sequence) { foreach (T element in sequence) return element;
throw new InvalidOperationException ("No elements!"); } }
var
1 2
var i = 10; // Implicitly typed. int i = 10; // Explicitly typed.
分部方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
namespace PM { partial class A { partial void OnSomethingHappened(string s); }
// This part can be in a separate file. partial class A { // Comment out this method and the program // will still compile. partial void OnSomethingHappened(String s) { Console.WriteLine("Something happened: {0}", s); } } }
对象和集合初始值设定项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
public class Cat { // Auto-implemented properties. public int Age { get; set; } public string Name { get; set; }
dynamic a = 3; a = 3.14; a = "Hello World"; a = new[] { 1, 2, 3, 4, 5 }; a = new Func<int>(() => 3); a = new StringBuilder(); Console.WriteLine(a.GetType().Name); // StringBuilder
private DamageResult CalculateDamageDone() { // Code omitted: // // Does an expensive calculation and returns // the result of that calculation. }
calculateButton.Clicked += async (o, e) => { // This line will yield control to the UI while CalculateDamageDone() // performs its work. The UI thread is free to perform other work. var damageResult = await Task.Run(() => CalculateDamageDone()); DisplayDamage(damageResult); };
public static int SumPositiveNumbers(IEnumerable<object> sequence) { int sum = 0; foreach (var i in sequence) { switch (i) { case 0: break; case IEnumerable<int> childSequence: { foreach(var item in childSequence) sum += (item > 0) ? item : 0; break; } case int n when n > 0: sum += n; break; case null: throw new NullReferenceException("Null found in sequence"); default: throw new InvalidOperationException("Unrecognized type"); } } return sum; }
本地函数
这个主要是方便,javascript就能这样写。
比lambda的好处在于,这个可以定义在后面,而lambda必须定义在前面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
public static IEnumerable<char> AlphabetSubset3(char start, char end) { if (start < 'a' || start > 'z') throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter"); if (end < 'a' || end > 'z') throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");
if (end <= start) throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");
return alphabetSubsetImplementation();
IEnumerable<char> alphabetSubsetImplementation() { for (var c = start; c < end; c++) yield return c; } }
更多的expression-bodied成员
该功能可以让一些函数写成表达式的形式,非常的方便。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Expression-bodied constructor public ExpressionMembersExample(string label) => this.Label = label;
public static ref int Find(int[,] matrix, Func<int, bool> predicate) { for (int i = 0; i < matrix.GetLength(0); i++) for (int j = 0; j < matrix.GetLength(1); j++) if (predicate(matrix[i, j])) return ref matrix[i, j]; throw new InvalidOperationException("Not found"); }
1 2 3 4
ref var item = ref MatrixSearch.Find(matrix, (val) => val == 42); Console.WriteLine(item); item = 24; Console.WriteLine(matrix[4, 2]);
public class Example { public static void Main() { var (_, _, _, pop1, _, pop2) = QueryCityDataForYears("New York City", 1960, 2010);
Console.WriteLine($"Population change, 1960 to 2010: {pop2 - pop1:N0}"); }
private static (string, double, int, int, int, int) QueryCityDataForYears(string name, int year1, int year2) { int population1 = 0, population2 = 0; double area = 0;
if (name == "New York City") { area = 468.48; if (year1 == 1960) { population1 = 7781984; } if (year2 == 2010) { population2 = 8175133; } return (name, area, year1, population1, year2, population2); }
return ("", 0, 0, 0, 0, 0); } } // The example displays the following output: // Population change, 1960 to 2010: 393,149
二进制文本和数字分隔符
这个用于使数字和二进制更可读。
1 2 3 4 5 6 7 8 9 10
// 二进制文本: public const int Sixteen = 0b0001_0000; public const int ThirtyTwo = 0b0010_0000; public const int SixtyFour = 0b0100_0000; public const int OneHundredTwentyEight = 0b1000_0000;
// 数字分隔符: public const long BillionsAndBillions = 100_000_000_000; public const double AvogadroConstant = 6.022_140_857_747_474e23; public const decimal GoldenRatio = 1.618_033_988_749_894_848_204_586_834_365_638_117_720_309_179M;
public static string RockPaperScissors(string first, string second) => (first, second) switch { ("rock", "paper") => "rock is covered by paper. Paper wins.", ("rock", "scissors") => "rock breaks scissors. Rock wins.", ("paper", "rock") => "paper covers rock. Paper wins.", ("paper", "scissors") => "paper is cut by scissors. Scissors wins.", ("scissors", "rock") => "scissors is broken by rock. Rock wins.", ("scissors", "paper") => "scissors cuts paper. Scissors wins.", (_, _) => "tie" };
位置模式
1 2 3 4 5 6 7 8 9 10
static Quadrant GetQuadrant(Point point) => point switch { (0, 0) => Quadrant.Origin, var (x, y) when x > 0 && y > 0 => Quadrant.One, var (x, y) when x < 0 && y > 0 => Quadrant.Two, var (x, y) when x < 0 && y < 0 => Quadrant.Three, var (x, y) when x > 0 && y < 0 => Quadrant.Four, var (_, _) => Quadrant.OnBorder, _ => Quadrant.Unknown };
static int WriteLinesToFile(IEnumerable<string> lines) { using var file = new System.IO.StreamWriter("WriteLines2.txt"); // Notice how we declare skippedLines after the using statement. int skippedLines = 0; foreach (string line in lines) { if (!line.Contains("Second")) { file.WriteLine(line); } else { skippedLines++; } } // Notice how skippedLines is in scope here. return skippedLines; // file is disposed here }
静态本地函数
相比非静态本地函数,静态本地函数没有闭包,因此生成的代码更少,性能也更容易控制。
1 2 3 4 5 6 7 8
int M() { int y = 5; int x = 7; return Add(x, y);
static int Add(int left, int right) => left + right; }
异步流
这个功能和IEnumerable<T>、Task<T>对应,一个经典的表格如下:
单值
多值
同步
T
IEnumerable
异步
Task
?
其中,这个问号?终于有了答案,它就叫异步流——IAsyncEnumerable<T>:
1 2 3 4 5 6 7 8
public static async System.Collections.Generic.IAsyncEnumerable<int> GenerateSequence() { for (int i = 0; i < 20; i++) { await Task.Delay(100); yield return i; } }
var words = new string[] { // index from start index from end "The", // 0 ^9 "quick", // 1 ^8 "brown", // 2 ^7 "fox", // 3 ^6 "jumped", // 4 ^5 "over", // 5 ^4 "the", // 6 ^3 "lazy", // 7 ^2 "dog" // 8 ^1 }; // 9 (or words.Length) ^0
var quickBrownFox = words[1..4]; var lazyDog = words[^2..^0]; var allWords = words[..]; // contains "The" through "dog". var firstPhrase = words[..4]; // contains "The" through "fox" var lastPhrase = words[6..]; // contains "the", "lazy" and "dog"
Null合并赋值
1 2 3 4 5 6 7 8 9
List<int> numbers = null; int? i = null;
numbers ??= new List<int>(); numbers.Add(i ??= 17); numbers.Add(i ??= 20);