1 Star 0 Fork 0

麦壳饼 / Learn-CSharp7Plus

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

C# 7+ Features

out variables

int numericResult;
if (int.TryParse(input, out numericResult))
    Console.WriteLine(numericResult);
else
    Console.WriteLine("Could not parse input");

// Since C# 7.0

if (int.TryParse(input, out int answer)) // or
if (int.TryParse(input, out var answer))
    Console.WriteLine(answer);
else
    Console.WriteLine("Could not parse input");

Tuples

var tuple = ("a", "b", 3);
Console.WriteLine(tuple.Item1); //a
Console.WriteLine(tuple.Item2); //b
Console.WriteLine(tuple.Item3); //3

(string First, string Last, int Age) tuple = ("a", "b", 3);
var tuple = (First: "a", Last: "b", Age: 3);
(string First, string Last, int Age) tuple = (First1: "a", Last: "b", Age: 3);
//The tuple element name 'First1' is ignored because a different name or no name is specified by the target type '(string First, string Last, int Age)'
Console.WriteLine(tuple.First); //a
Console.WriteLine(tuple.Last);  //b
Console.WriteLine(tuple.Age);   //3

var name = "heku";
var age = 20;
var tuple = (name, age); // C# 7.1

private static (int Max, int Min) Range(IEnumerable<int> numbers)
{
    int min = int.MaxValue;
    int max = int.MinValue;
    foreach (var n in numbers)
    {
        min = (n < min) ? n : min;
        max = (n > max) ? n : max;
    }
    return (max, min);
}

var range = Range(Enumerable.Range(1, 100));		// range.Max=100, range.Min=1
(int max,var min) = Range(Enumerable.Range(1, 100));	// max=100, min=1
(var max, _) = Range(Enumerable.Range(1, 100));		// max=100
var (max, min) = Range(Enumerable.Range(1, 100));	// max=100, min=1
var (max, _) = Range(Enumerable.Range(1, 100));		// max=100

var a = (1,2,3);
var b = (a:1,b:2,c:3);
a == b; // true  C# 7.3
  • The new tuples features require the ValueTuple types. You must add the NuGet package System.ValueTuple in order to use it on platforms that do not include the types.
  • It's perferred for private and internal methods

Deconstruct Method

public class/struct Point
{
    public Point(double x, double y, double z)
    {
        this.X = x;
        this.Y = y;
        this.Z = z;
    }
    public double X { get; }
    public double Y { get; }
    public double Z { get; }
    public void Deconstruct(out double x, out double y)
    {
        x = this.X;
        y = this.Y;
    }
    public void Deconstruct(out double x, out double y, out double z)
    {
        x = this.X;
        y = this.Y;
        z = this.Z;
    }
}
var p = new Point(1, 2, 3);
var (a, b) = p;		// a=1,b=2
var (x, y, z) = p;	// x=1,y=2,z=3

public static void Deconstruct(this DateTime date, out int year, out int month, out int day)
{
    year = date.Year;
    month = date.Month;
    day = date.Day;
}
var (year, month, day) = DateTime.Today;

Discards _

  • out parameters
  • Deconstruction
  • is, switch pattern matching

Pattern Matching

double? num = xxx;

if(num is null){}
if(num is 0) {}
if(num is double n && n>0) {}
if(num is var other){}

switch (num)
{
    case 0:
        Console.WriteLine("zero");
        break;
    case double n when n > 0:
        Console.WriteLine("positive");
        break;
    case double n when n < 0:
        Console.WriteLine("negative");
        break;
    case null:
        Console.WriteLine("num=null");
        break;
    default:
        Console.WriteLine("Not a number");
        break;
}
  • The order of the case expressions now matters
  • The default case is always evaluated last

Local Functions

static IEnumerable<int> GetYears(int from, int to)
{
    if (from <= 0) throw new ArgumentOutOfRangeException(nameof(from));
    if (to <= 0) throw new ArgumentOutOfRangeException(nameof(to));
    if (from > to) throw new ArgumentException();

    for (int year = from; year <= to; year++)
    {
        yield return year;
    }
}
var years = GetYears(0, 10);
Console.WriteLine("GetYears Called");
foreach (var year in years)
{
    Console.WriteLine(year);
}

static IEnumerable<int> GetYears(int from, int to)
{
    if (from <= 0) throw new ArgumentOutOfRangeException(nameof(from));
    if (to <= 0) throw new ArgumentOutOfRangeException(nameof(to));
    if (from > to) throw new ArgumentException();

    return GetYearsInternal();

    IEnumerable<int> GetYearsInternal()
    {
        for (int year = from; year <= to; year++)
        {
            yield return year;
        }
    }
}

// --------------------------------

static async Task<string> GetWebContent(string url)
{
    if (string.IsNullOrWhiteSpace(url)) throw new ArgumentException(nameof(url));

    await Task.Delay(2000); // Get content from url
    return "web content from :" + url;
}

var task = GetWebContent(null);
Console.WriteLine("GetWebContent Called");
var content = await task;
Console.WriteLine(content);

static Task<string> GetWebContent(string url)
{
    if (string.IsNullOrWhiteSpace(url)) throw new ArgumentException(nameof(url));

    return GetWebContentInternal();

    async Task<string> GetWebContentInternal()
    {
        await Task.Delay(2000); // Get content from url
        return "web content from :" + url;
    }
}

More expression-bodied members

// Expression-bodied constructor
public ExpressionMembersExample(string label) => this.Label = label;

// Expression-bodied finalizer
~ExpressionMembersExample() => Console.Error.WriteLine("Finalized!");

private string label;

// Expression-bodied get / set accessors.
public string Label
{
    get => label;
    set => this.label = value ?? "Default label";
}

Throw expressions

public string Name
{
    get => name;
    set => name = value ?? throw new ArgumentNullException(paramName: nameof(value), message: "New name must not be null");
}
private ConfigResource loadedConfig = LoadConfigResourceOrDefault() ?? throw new InvalidOperationException("Could not load config");

Generalized async return types

public async ValueTask<int> Func()
{
    await Task.Delay(100);
    return 5;
}

Numeric literal syntax improvements

public const int One =  0b0001;
public const int Two =  0b0010;
public const int Four = 0b0100;
public const int Eight = 0b1000;

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;

int num = 0x_FFFF; // C# 7.2
int num = 0b_1111_1111_1111_1111; // C# 7.2

Async Main (7.1)

	static async Task Main() {...}
	static async Task Main(string[] args) {...}
	static async Task<int> Main() {...}
	static async Task<int> Main(string[] args) {...}

default Literal Expressions (7.1)

	// Before
	int num = default(int);
	object obj = default(object);
	DateTime time = default(DateTime);

	T Method<T>(CancellationToken token = default(CancellationToken))
	{
	    T value = default(T);
	    return default(T);
	}

	Method<int>(default(CancellationToken));
	
	// Since C# 7.1
	int num = default;
	object obj = default;
	DateTime time = default;

	T Method<T>(CancellationToken token = default)
	{
	    T value = default;
	    return default;
	}

	Method<int>(default);

private protected Access Modifier (7.2)

  • private protected indicates that a member may be accessed by containing class or derived classes that are declared in the same assembly
  • protected internal allows access by derived classes or classes that are in the same assembly

Non-trailing named arguments (7.2)

static void Method(string a = "a", string b = "b", string c = "c") {...}
// Error: Named argument specifications must appear after all fixed arguments have been specified. Please use language version 7.2 or greater to allow non-trailing named arguments.
Method(a:"a", "b", "c");	

Attach attributes to the backing field for AIP (7.3)

[field: SomeThingAboutFieldAttribute]
public int SomeProperty { get; set; }

Others

  • ref locals and returns (7.0)
  • Reference value types (in,ref readonly,readonly struct,ref struct) (7.2)
  • Conditional ref expressions (7.2)
  • You can access fixed fields without pinning. (7.3)
  • You can reassign ref local variables. (7.3)
  • You can use initializers on stackalloc arrays. (7.3)
  • You can use fixed statements with any type that supports a pattern. (7.3)
  • You can use additional generic constraints. (7.3)
  • You can use expression variables in more locations. (7.3)
  • Method resolution when arguments differ by in has been improved. (7.3)
  • Overload resolution now has fewer ambiguous cases. (7.3)

Reference

空文件

简介

学习C# 7 语法的非常好的例子 展开 收起
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
C#
1
https://gitee.com/maikebing/Learn-CSharp7Plus.git
git@gitee.com:maikebing/Learn-CSharp7Plus.git
maikebing
Learn-CSharp7Plus
Learn-CSharp7Plus
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891