代码演示C#各版本新功能

代码演示C#各版本新功能

C#各版本新功能其实都能在官网搜到,但很少有人整理在一起,并通过非常简短的代码将每个新特性演示出来。

  • 代码演示C#各版本新功能

  • C# 2.0版 - 2005

    • 泛型

    • 分部类型

    • 匿名方法

    • 可以为null的值类型

    • 迭代器

    • 协变和逆变

  • C# 3.0版 - 2007

    • 自动实现的属性

    • 匿名类型

    • 查询表达式(LINQ)

    • Lambda表达式

    • 表达式树

    • 扩展方法

    • var

    • 分部方法

    • 对象和集合初始值设定项

  • C# 4.0版 - 2010

    • dynamic

    • 命名参数/可选参数

    • 泛型中的协变和逆变

    • 类型等效、内置互操作类型

  • C# 5.0版 - 2012

    • async/await

    • 调用方信息

  • C# 6.0版 - 2015

    • 静态导入

    • 异常筛选器

    • 自动初始化表达式

    • Expression-bodied 函数成员

    • Null传播器

    • 字符串内插

    • nameof表达式

    • 索引初始值设定项

  • C# 7.0版本 - 2017

    • out变量

    • 元组和析构函数

    • 模式匹配

    • 本地函数

    • 更多的expression-bodied成员

    • Ref 局部变量和返回结果

    • 弃元

    • 二进制文本和数字分隔符

    • throw表达式

  • C# 8.0 版 - 2019

    • Readonly 成员

    • 默认接口方法

    • 模式匹配增强

    • 属性模式

    • Tuple模式

    • 位置模式

    • switch表达式

    • using声明

    • 静态本地函数

    • 异步流

    • 索引和范围

    • Null合并赋值

    • 非托管构造类型

    • 嵌套表达式中的 stackalloc

  • 附录/总结

C# 2.0版 - 2005

泛型

Java中的泛型不支持值类型,且会运行时类型擦除,这一点 .NET更优秀。

// 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());}
}

分部类型

拆分一个类、一个结构、一个接口或一个方法的定义到两个或更多的文件中是可能的。每个源文件包含类型或方法定义的一部分,编译应用程序时将把所有部分组合起来。

public partial class Employee
{public void DoWork(){}
}
public partial class Employee
{public void GoToLunch(){}
}

匿名方法

Func<int, int, int> sum = delegate (int a, int b) { return a + b; };
Console.WriteLine(sum(3, 4));  // output: 7

可以为null的值类型

double? pi = 3.14;
char? letter = 'a';
int m2 = 10;
int? m = m2;
bool? flag = null;
// An array of a nullable type:
int?[] arr = new int?[10];

迭代器

static void Main()
{foreach (int number in SomeNumbers()){Console.Write(number.ToString() + " ");}// Output: 3 5 8Console.ReadKey();
}
public static System.Collections.IEnumerable SomeNumbers()
{yield return 3;yield return 5;yield return 8;
}

协变和逆变

在 C# 中,协变和逆变能够实现数组类型、委托类型和泛型类型参数的隐式引用转换。协变保留分配兼容性,逆变则与之相反。

// 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;

C# 3.0版 - 2007

自动实现的属性

// This class is mutable. Its data can be modified from
// outside the class.
class Customer
{// Auto-implemented properties for trivial get and setpublic double TotalPurchases { get; set; }public string Name { get; set; }public int CustomerID { get; set; }// Constructorpublic Customer(double purchases, string name, int ID){TotalPurchases = purchases;Name = name;CustomerID = ID;}// Methodspublic 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;}
}

匿名类型

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#代码,像这样:

from p in persons
where p.Age > 18 && p.IsBeatiful
select new
{p.WeChatId, p.PhoneNumber
}

LINQ的意义在于让 C#做出了重大调整,本章中说到的 lambda表达式、扩展方法、表达式树、匿名类型、自动属性等,都是 LINQ的必要组成部分。

由于用扩展方法的形式也能得到一致的结果,而且还能让代码风格更加一致,所以我平时用 LINQ语法较少:

// 与上文代码相同,但改成了扩展方法风格:
persons.Where(x => x.Age > 18 && x.IsBeatiful).Select(x => new {x.WeChatId, x.PhoneNumber, });

Lambda表达式

Func<int, int> square = x => x * x;
Console.WriteLine(square(5));
// Output:
// 25

表达式树

这个是 LINQ的基础之一,它的作用是将代码像数据一样,保存在内存中;然后稍后对这些“代码数据”进行重新解释/执行。

EntityFramework就是一个经典场景,它先将表达式树保存起来,然后执行时,将其翻译为 SQL发给数据库执行。

注意:表达式树并不能表示所有的代码, C# 3.0之后的语法,包含 ??、 ?.、 asyncawait、可选参数等,都无法放到表达式树中。据说官方准备更新它,但迟迟没有进展。

扩展方法

扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。

static void Main()
{Console.WriteLine ("Perth".IsCapitalized());    // Equivalent to:Console.WriteLine (StringHelper.IsCapitalized ("Perth"));   // 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

var i = 10; // Implicitly typed.
int i = 10; // Explicitly typed.

分部方法

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);}}
}

对象和集合初始值设定项

public class Cat
{// Auto-implemented properties.public int Age { get; set; }public string Name { get; set; }public Cat(){}public Cat(string name){this.Name = name;}
}

C# 4.0版 - 2010

dynamic

这个是特性使得 CLR不得不进行一次修改。有了这个, C#也能像 js、 php、 python等弱类型语言一样写代码了。

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

注意 dynamic可以表示任何东西,包含数组、委托等等。滥用 dynamic容易让程序变得很难维护。

命名参数/可选参数

PrintOrderDetails(productName: "Red Mug", sellerName: "Gift Shop", orderNum: 31);
public void ExampleMethod(int required, string optionalstr = "default string",int optionalint = 10)

泛型中的协变和逆变

IEnumerable<Derived> d = new List<Derived>();
IEnumerable<Base> b = d;
Action<Base> b = (target) => { Console.WriteLine(target.GetType().Name); };
Action<Derived> d = b;
d(new Derived());

类型等效、内置互操作类型

这个主要是为了和 COM进行交互。之前需要引用一些 COM类型相关的程序集,现在可以直接引用 COM。具体可以参见:https://docs.microsoft.com/zh-cn/dotnet/framework/interop/type-equivalence-and-embedded-interop-types

C# 5.0版 - 2012

async/await

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);
};

asyncawait的本质是状态机,像 IEnumerable<T>一样。以前游戏引擎 Unity只支持 C# 3.0,因此当时它用状态机发 Http请求是用的 IEnumerable<T>

asyncawait有两个好处,一是可以避免 UI线程卡顿,二是提高系统吞吐率,最终提高性能。

调用方信息

public void DoProcessing()
{TraceMessage("Something happened.");
}
public void TraceMessage(string message,[CallerMemberName] string memberName = "",[CallerFilePath] string sourceFilePath = "",[CallerLineNumber] int sourceLineNumber = 0)
{System.Diagnostics.Trace.WriteLine("message: " + message);System.Diagnostics.Trace.WriteLine("member name: " + memberName);System.Diagnostics.Trace.WriteLine("source file path: " + sourceFilePath);System.Diagnostics.Trace.WriteLine("source line number: " + sourceLineNumber);
}
// Sample Output:
//  message: Something happened.
//  member name: DoProcessing
//  source file path: c:\Visual Studio Projects\CallerInfoCS\CallerInfoCS\Form1.cs
//  source line number: 31

注意这个是编译期生成的,因此比 StackTrace更能保证性能。

C# 6.0版 - 2015

静态导入

终于可以不用写静态类名了。

using static System.Math;
using static System.Console;
WriteLine(Sin(3.14)); // 0.00159265291648683

异常筛选器

在 try-catch时,可以按指定的条件进行 catch,其它条件不 catch

public static async Task<string> MakeRequest()
{WebRequestHandler webRequestHandler = new WebRequestHandler();webRequestHandler.AllowAutoRedirect = false;using (HttpClient client = new HttpClient(webRequestHandler)){var stringTask = client.GetStringAsync("https://docs.microsoft.com/en-us/dotnet/about/");try{var responseText = await stringTask;return responseText;}catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301")){return "Site Moved";}}
}

自动初始化表达式

public ICollection<double> Grades { get; } = new List<double>();

Expression-bodied 函数成员

public override string ToString() => $"{LastName}, {FirstName}";

Null传播器

var first = person?.FirstName;

字符串内插

public string GetGradePointPercentage() =>$"Name: {LastName}, {FirstName}. G.P.A: {Grades.Average():F2}";

nameof表达式

有时字符串值和某个变量名称一致,尤其是在做参数验证时。这里 nameof就能在编译期,自动从变量名生成一个字符串。

if (IsNullOrWhiteSpace(lastName))throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));

索引初始值设定项

使集合初始化更容易的另一个功能是对 Add 方法使用扩展方法 。添加此功能的目的是进行 Visual Basic 的奇偶校验。如果自定义集合类的方法具有通过语义方式添加新项的名称,则此功能非常有用。

C# 7.0版本 - 2017

out变量

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

元组和解构函数

(string Alpha, string Beta) namedLetters = ("a", "b");
Console.WriteLine($"{namedLetters.Alpha}, {namedLetters.Beta}");

解构是将元组转换为变量。//忽略…构函数应该类似C++中的析构函数,在实例回收时执行?

模式匹配

现在可以在匹配一个类型时,自动转换为这个类型的变量,如果转换失败,这个变量就赋值为默认值( null或 0)。

极简版:

if (input is int count)sum += count;

switch/case版:

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必须定义在前面。

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成员

该功能可以让一些函数写成表达式的形式,非常的方便。

// 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";
}

Ref 局部变量和返回结果

此功能允许使用并返回对变量的引用的算法,这些变量在其他位置定义。一个示例是使用大型矩阵并查找具有某些特征的单个位置。

这个功能主要是为了提高值类型的性能,让它真正发挥其作用。 C++就有类似的功能。

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");
}
ref var item = ref MatrixSearch.Find(matrix, (val) => val == 42);
Console.WriteLine(item);
item = 24;
Console.WriteLine(matrix[4, 2]);

弃元

通常,在进行元组解构或使用 out参数调用方法时,必须定义一个其值无关紧要且你不打算使用的变量。为处理此情况, C#增添了对弃元的支持 。弃元是一个名为 _的只写变量,可向单个变量赋予要放弃的所有值。弃元类似于未赋值的变量;不可在代码中使用弃元(赋值语句除外)。

using System;
using System.Collections.Generic;
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

二进制文本和数字分隔符

这个用于使数字和二进制更可读。

// 二进制文本:
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;

throw表达式

throw之前必须是一个语句,因此有时不得不写更多的代码来完成所需功能。但 7.0提供了 throw表达式来使代码更简洁,阅读更轻松。

void Main()
{// You can now throw expressions in expressions clauses.// This is useful in conditional expressions:string result = new Random().Next(2) == 0 ? "Good" : throw new Exception ("Bad");result.Dump();Foo().Dump();
}
public string Foo() => throw new NotImplementedException();

C# 8.0 版 - 2019

Readonly 成员

public readonly override string ToString() =>$"({X}, {Y}) is {Distance} from the origin";

默认接口方法

接口中也能定义方法了,这个新功能经常受到争论。但想想,有时是先定义接口,而实现接口需要实现很多相关、但又繁琐的功能,如 ASP.NETCore中的 ILogger,谁用谁知道,特别多需要实现的方法,但又都差不多。因此所以这个功能其实很有必要。

void Main()
{ILogger foo = new Logger();foo.Log (new Exception ("test"));   
}
class Logger : ILogger
{    public void Log (string message) => Console.WriteLine (message);
}
interface ILogger
{void Log (string message);  // Adding a new member to an interface need not break implementors:public void Log (Exception ex) => Log (ExceptionHeader + ex.Message);// The static modifier (and other modifiers) are now allowed:static string ExceptionHeader = "Exception: ";
}

模式匹配增强

这个是为简化代码、函数式编程而生的,我个人非常喜欢。

属性模式

public static decimal ComputeSalesTax(Address location, decimal salePrice) =>location switch{{ State: "WA" } => salePrice * 0.06M,{ State: "MN" } => salePrice * 0.75M,{ State: "MI" } => salePrice * 0.05M,// other cases removed for brevity..._ => 0M};

Tuple模式

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"};

位置模式

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
};

switch表达式

这个功能能使代码从大量的 if/else或 switch/case变成“一行代码”,符合函数式编程的思想,非常好用!

public static RGBColor FromRainbow(Rainbow colorBand) =>colorBand switch{Rainbow.Red    => new RGBColor(0xFF, 0x00, 0x00),Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),Rainbow.Green  => new RGBColor(0x00, 0xFF, 0x00),Rainbow.Blue   => new RGBColor(0x00, 0x00, 0xFF),Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),_              => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),};

using声明

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
}

静态本地函数

相比非静态本地函数,静态本地函数没有闭包,因此生成的代码更少,性能也更容易控制。

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>对应,一个经典的表格如下:


单值多值
同步TIEnumerable
异步Task?

其中,这个问号 ?终于有了答案,它就叫异步流—— IAsyncEnumerable<T>

public static async System.Collections.Generic.IAsyncEnumerable<int> GenerateSequence()
{for (int i = 0; i < 20; i++){await Task.Delay(100);yield return i;}
}

不像 IEnumerable<T>, IAsyncEnumerable<T>系统还没有内置扩展方法,因此可能没有 IEnumerable<T>方便,但是可以通过安装 NuGet包 f来实现和 IEnumerable<T>一样(或者更爽)的效果。

索引和范围

和 Python中的切片器一样,只是 -用 ^代替了。

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合并赋值

List<int> numbers = null;
int? i = null;
numbers ??= new List<int>();
numbers.Add(i ??= 17);
numbers.Add(i ??= 20);
Console.WriteLine(string.Join(" ", numbers));  // output: 17 17
Console.WriteLine(i);  // output: 17

非托管构造类型

与任何非托管类型一样,可以创建指向此类型的变量的指针,或针对此类型的实例在堆栈上分配内存块

Span<Coords<int>> coordinates = stackalloc[]
{new Coords<int> { X = 0, Y = 0 },new Coords<int> { X = 0, Y = 3 },new Coords<int> { X = 4, Y = 0 }
};

嵌套表达式中的 stackalloc

Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };
var ind = numbers.IndexOfAny(stackalloc[] { 2, 4, 6 ,8 });
Console.WriteLine(ind);  // output: 1

附录/总结

这么多功能,你印象最深刻的是哪个呢?

参考资料:C#发展历史 - C#指南 | Microsoft Docs 

https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-version-history

本文内容和代码由肖鹏整理,有大量修改;转载已获得肖鹏本人授权。肖鹏是我公司从 Java转 .NET的同事。原文链接为:https://akiyax.github.io/new-features-in-csharp/。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311454.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《C++ Primer》1.52节练习

练习1.23 #include <iostream> #include "Sales_item.h"using namespace std;int main() {Sales_item trans1, trans2;cout << "请输入若干销售记录:" << endl;if (cin >> trans1) {int num 1;while (cin >> trans2)if (t…

ASP.NET Core 反向代理部署知多少

引言最近在折腾统一认证中心&#xff0c;看到开源项目[IdentityServer4.Admin&#xff1a;https://github.com/skoruba/IdentityServer4.Admin]集成了IdentityServer4和管理面板&#xff0c;就直接拿过来用了。在尝试Nginx部署时遇到了诸如虚拟目录映射&#xff0c;请求头超长、…

函数传参string_JavaScript 高阶函数入门浅析

原文&#xff1a;https://www.freecodecamp.org/news/a-quick-intro-to-higher-order-functions-in-javascript-1a014f89c6b/译者&#xff1a;jingruzhang校对者&#xff1a;acusp高阶函数高阶函数可以接收函数作为参数&#xff0c;同时也可以返回一个新的函数。高阶函数之所以…

.NET Core开发实战(第13课:配置绑定:使用强类型对象承载配置数据)--学习笔记...

13 | 配置绑定&#xff1a;使用强类型对象承载配置数据要点&#xff1a;1、支持将配置值绑定到已有对象2、支持将配置值绑定到私有属性上继续使用上一节代码首先定义一个类作为接收配置的实例class Config {public string Key1 { get; set; }public bool Key5 { get; set; }pub…

工业互联网白皮书_发布|《工业互联网平台安全白皮书(2020)》发布

12月4日&#xff0c;2020年中国工业信息安全大会暨全国工控安全深度行(京津冀站)在北京国际会议中心举行。大会由国家工业信息安全发展研究中心、工业信息安全产业发展联盟主办&#xff0c;以“贯彻总体国家安全观&#xff0c;把牢工控安全基准线”为主题。会上&#xff0c;国家…

ASP.NET Core Razor 视图预编译、动态编译

0x01 前言ASP.NET Core在默认发布情况下&#xff0c;会启动预编译将试图编译成xx.Views.dll,也许在视图中打算修改一处很细小的地方我们需要再重新编译视图进行发布。下面我将从 ASP.NET Core 3 之前版本到 ASP.NET Core 3X 之后版本的一个配置列下下方供大家参考。0x02 预编译…

《C++ Primer》2.1.2节练习

练习2.3 #include <iostream> using namespace std;int main() {unsigned u 10, u2 42;cout << u2 - u << endl;cout << u - u2 << endl;int i 10, i2 42;cout << i2 - i << endl;cout << i - i2 << endl;cout <…

如何构建基于.NET Core和云环境下的微服务技术体系?

这个内核用处不大&#xff0c;但.NET 内核却666随着业务需求的增长&#xff0c;我们现在开发非常大型和复杂的项目&#xff0c;需要更多时间来构建和部署。每当质量检查报告任何问题时&#xff0c;我们都需要对其进行调试或修复&#xff0c;然后部署整个代码。为了降低这些复杂…

UVA - 11059 Maximum Product-暴力枚举

输入n个元素组成的序列s,找出一个乘积最大的连续子序列&#xff0c;如果这个子序列不是整数&#xff0c;则输出0. 解题思路&#xff1a; 枚举起点和终点&#xff0c;把中间的数相乘&#xff0c;然后找到最大的结果。 代码如下&#xff1a; #include <iostream> using…

好用的vp n推荐2020_哪个牌子的沐浴露好,2020年最新沐浴露选购测评,好用好闻易清洗沐浴露品牌推荐...

您好&#xff0c;感谢您关注并阅读本文。声明&#xff1a;本文系作者原创&#xff0c;未经作者授权不得转载、引用。如果您看完本文觉得对您有帮助&#xff0c;请点赞、收藏和关注&#xff0c;作者感激不尽。本文详细地介绍一下沐浴露使用方法和选购建议指南&#xff0c;以及沐…

【朝夕Net社区技术专刊】Core3.1 WebApi集群实战专题---WebApi环境搭建运行发布部署篇...

欢迎大家阅读《朝夕Net社区技术专刊》第1期我们致力于.NetCore的推广和落地&#xff0c;为更好的帮助大家学习&#xff0c;方便分享干货&#xff0c;特创此刊&#xff01;很高兴你能成为首期读者&#xff0c;文末福利不要错过哦&#xff01;本文通过5大部分进行解读&#xff1a…

【朝夕Net社区技术专刊】Core3.1 WebApi集群实战专题-Corre3.1WebApi配置集成日志/配置Swagger...

欢迎大家阅读《朝夕Net社区技术专刊》第2期我们致力于.NetCore的推广和落地&#xff0c;为更好的帮助大家学习&#xff0c;方便分享干货&#xff0c;特创此刊&#xff01;很高兴你能成为首期读者&#xff0c;文末福利不要错过哦&#xff01;本文通过3大部分进行解读&#xff1a…

一文读懂开源许可证异同

对开源许可证异同的对比并非源自担忧。对开源许可证进行比较并不容易&#xff0c;什么 copyleft 啦&#xff0c;什么宽松许可证啦&#xff0c;光 GNU 就有 GPL 2 和 GPL 3 之分&#xff0c;OSI 批准的许可证就有八十多个&#xff0c;而开源生态下存在了数百个许可证。对于我们这…

WARNING: Ignoring invalid distribution -ip

原因: 之前安装插件失败/中途退出&#xff0c;导致插件安装出现异常导致 解决方案: 进入你的项目里面,进入venv文件夹,进入Lib,进入site-packages,删除~ip开头的文件如图所示

根据后序和中序求二叉树的层序

题目描述&#xff1a;给出二叉树的后序和中序序列&#xff0c;输出二叉树的层序遍历序列。 题目分析&#xff1a;中序遍历为左根右&#xff0c;后序遍历为左右根&#xff0c;所以后序遍历的最后一个节点为根节点&#xff0c;在中序遍历上找出根节点的位置&#xff0c;将树分为…

mysql数据剪切到新表_6、MySQL核心DDL语句

命令类型服务器端命令获取命令帮助数据库管理查看数据库基础变量SQL组成创建修改删除表管理创建示例一示例二示例三一个常见的创建表结构的示例表修改改名表结构修改添加/删除字段修改字段键管理索引索引管理视图视图操作命令类型服务器端命令DDL&#xff1a;数据定义语言&…

pycharm里面下载pip(不用去官网)

注意:pycharm版本较低的话右侧有个"",一样的效果