[翻译]欢迎使用C#9.0

本文由公众号[开发者精选资讯](微信号:yuantoutiao)翻译首发,转载请注明来源

C# 9.0 is taking shape, and I’d like to share our thinking on some of the major features we’re adding to this next version of the language.

C#9.0初具规模,我想就我们要添加到该语言下一版本中的一些主要功能分享我们的想法。

With every new version of C# we strive for greater clarity and simplicity in common coding scenarios, and C# 9.0 is no exception. One particular focus this time is supporting terse and immutable representation of data shapes.

在C#的每个新版本中,我们都在通用编码方案中力求更加清晰和简单,C#9.0也不例外。这次的一个特别重点是支持数据类的简洁和不变数据的表示形式。

Let’s dive in!

让我们开始吧!

Init-only properties

仅需初始化的属性

Object initializers are pretty awesome. They give the client of a type a very flexible and readable format for creating an object, and they are especially great for nested object creation where a whole tree of objects is created in one go. Here’s a simple one:

对象初始化器非常棒。它们为类型实例提供了一种非常灵活且易于读取的格式来创建对象,并且特别适合嵌套对象的创建,在该对象中一次性创建了整个对象树。这是一个简单的例子:

new Person
{FirstName = "Scott",LastName = "Hunter"
}

Object initializers also free the type author from writing a lot of construction boilerplate – all they have to do is write some properties!

对象初始值设定可以使开发人员免于编写大量样板代码–他们要写一些属性!

public class Person
{public string FirstName { get; set; }public string LastName { get; set; }
}

The one big limitation today is that the properties have to be mutable for object initializers to work: They function by first calling the object’s constructor (the default, parameterless one in this case) and then assigning to the property setters.

现在的一大局限性在于,属性必须是可变的,对象初始化程序才能起作用:它们通过首先调用对象的构造函数(在这种情况下为默认的,无参数的)来工作,然后赋值给属性setter方法。

Init-only properties fix that! They introduce an init accessor that is a variant of the set accessor which can only be called during object initialization:

仅初始化属性可以解决该问题!它们引入了init访问器,它是访问器的变体,set只能在对象初始化期间调用它:

public class Person
{public string FirstName { get; init; }public string LastName { get; init; }
}

With this declaration, the client code above is still legal, but any subsequent assignment to the FirstName and LastName properties is an error.

使用此声明,上面的客户端代码仍然合法,但是随后对FirstNameLastName属性的任何赋值都是错误的。

Init accessors and readonly fields

初始化访问器和只读字段

Because init accessors can only be called during initialization, they are allowed to mutate readonly fields of the enclosing class, just like you can in a constructor.

由于init访问器只能在初始化期间被调用,因此允许它们改变封闭类readonly的字段,就像在构造函数中一样。

public classPerson{private readonly string firstName;private readonly string lastName;public string FirstName{get => firstName;init => firstName = (value ?? throw new ArgumentNullException(nameof(FirstName)));}public string LastName{get => lastName;init => lastName = (value ?? throw new ArgumentNullException(nameof(LastName)));}
}

Records

记录类

Init-only properties are great if you want to make individual properties immutable. If you want the whole object to be immutable and behave like a value, then you should consider declaring it as a record:

如果要使单个属性不变,则仅初始化属性非常有用。如果您希望整个对象是不可变的并且表现得像一个值,那么您应该考虑将其声明为记录

public data class Person
{public string FirstName { get; init; }public string LastName { get; init; }
}

The data keyword on the class declaration marks it as a record. This imbues it with several additional value-like behaviors, which we’ll dig into in the following. Generally speaking, records are meant to be seen more as “values” – data! – and less as objects. They aren’t meant to have mutable encapsulated state. Instead you represent change over time by creating new records representing the new state. They are defined not by their identity, but by their contents.

在类声明时使用data关键词标记一个记录类。这使它附加了其他一些类似于值的行为,我们将在下面对此进行深入研究。一般而言,记录类应更多地视为“值” –数据!–而不是作为对象。也就是说这个类成了不可改变的状态。您可以通过创建表示新状态的新记录来表示随着时间的变化的记录。它们不是由其身份定义的,而是由其内容定义的。

With-expressions

with 表达式

When working with immutable data, a common pattern is to create new values from existing ones to represent a new state. For instance, if our person were to change their last name we would represent it as a new object that’s a copy of the old one, except with a different last name. This technique is often referred to as non-destructive mutation. Instead of representing the person over time, the record represents the person’s state at a given time.

处理不可变数据时,一种常见的模式是从现有值创建新值以表示新状态。例如,如果我们的人要更改其姓氏,则将其表示为一个新对象,该对象是旧对象的副本,但姓氏不同。这种技术通常被称为非破坏性突变。记录不代表一段时间内的人而是代表给定时间的人的状态。

To help with this style of programming, records allow for a new kind of expression; the with-expression:

为了帮助这种编程风格,记录允许一种新的表达方式 —— with表达式:

var otherPerson = person with { LastName = "Hanselman" };

With-expressions use object initializer syntax to state what’s different in the new object from the old object. You can specify multiple properties.

With-expressions使用对象初始化器语法来声明新对象与旧对象的不同之处。您可以指定多个属性。

A record implicitly defines a protected “copy constructor” – a constructor that takes an existing record object and copies it field by field to the new one:

一条记录隐式定义了一个protected“复制构造函数” –一种构造函数,它接受现有的记录对象并将其逐字段复制到新的记录对象中:

protected Person(Person original){ /* copy all the fields */ } // generated

The with expression causes the copy constructor to get called, and then applies the object initializer on top to change the properties accordingly.

with表达式使副本构造函数被调用,然后在顶部应用对象初始化程序以相应地更改属性。

If you don’t like the default behavior of the generated copy constructor you can define your own instead, and that will be picked up by the with expression.

如果您不喜欢所生成的副本构造函数的默认行为,则可以定义自己的副本构造函数,并将其由with表达式提取。

值类型的相等性判断

All objects inherit a virtual Equals(object) method from the object class. This is used as the basis for the Object.Equals(object, object) static method when both parameters are non-null.

所有对象都从object类继承一个虚拟方法 Equals(object)。当两个参数都不为空时,它将用作静态方法 objectObject.Equals(object, object)  的基础相等性判断。

Structs override this to have “value-based equality”, comparing each field of the struct by calling Equals on them recursively. Records do the same.

结构体重载此方法以具有“基于值的相等性”,通过Equals递归调用结构来比较结构的每个字段。记录和结构体一样。

This means that in accordance with their “value-ness” two record objects can be equal to one another without being the same object. For instance if we modify the last name of the modified person back again:

这意味着,根据两个记录对象的值判断相等性,而不必是同一对象。例如,如果我们再次修改已修改人员的姓氏:

var originalPerson = otherPerson with { LastName = "Hunter" };

We would now have ReferenceEquals(person, originalPerson) = false (they aren’t the same object) but Equals(person, originalPerson) = true (they have the same value).

现在,我们将有 ReferenceEquals(person, originalPerson)= false(它们不是同一对象),但Equals(person, originalPerson)= true(它们具有相同的值)。

If you don’t like the default field-by-field comparison behavior of the generated Equals override, you can write your own instead. You just need to be careful that you understand how value-based equality works in records, especially when inheritance is involved, which we’ll come back to below.

如果您不喜欢默认的逐域比较行为,则可以重写Equals方法。您只需要注意了解基于值的相等性在记录中的工作原理,尤其是在涉及继承时,我们将再下面文章中回到这个问题上。

Along with the value-based Equals there’s also a value-based GetHashCode() override to go along with it.

除了基于值判断的 Equals 方法外,还有一个 GetHashCode() 方法,可以重写。


Data members

数据成员

Records are overwhelmingly intended to be immutable, with init-only public properties that can be non-destructively modified through with-expressions. In order to optimize for that common case, records change the defaults of what a simple member declaration of the form string FirstName means. Instead of an implicitly private field, as in other class and struct declarations, in records this is taken to be shorthand for a public, init-only auto-property! Thus, the declaration:

记录绝大多数都是不可变的,它们具有只能通过with表达式进行非破坏性修改的仅初始化的公共属性。为了针对这种常见情况进行优化,记录更改了表单的简单成员声明的含义的默认值。代替其他类和结构声明中的隐式私有字段,在记录中将其视为公共的,仅用于初始化的自动属性的简写!因此,声明:string FirstName

public data class Person { string FirstName; string LastName; }

Means exactly the same as the one we had before:

与之前使用如下代码完全相同:

public data class Person
{public string FirstName { get; init; }public string LastName { get; init; }
}

We think this makes for beautiful and clear record declarations. If you really want a private field, you can just add the private modifier explicitly:

我们认为这可以使记录声明优美而清晰。如果您确实想要私有字段,则可以private显式添加修饰符:

private string firstName;

Positional records

位置记录

Sometimes it’s useful to have a more positional approach to a record, where its contents are given via constructor arguments, and can be extracted with positional deconstruction.

有时,对记录采用具位置定位的方法很有用,该记录的内容是通过构造函数参数指定的,并且可以通过位置解构来提取。

It’s perfectly possible to specify your own constructor and deconstructor in a record:

完全有可能在记录中指定您自己的构造函数和解构函数:

public data class Person 
{ string FirstName; string LastName; public Person(string firstName, string lastName) => (FirstName, LastName) = (firstName, lastName);public void Deconstruct(out string firstName, out string lastName) => (firstName, lastName) = (FirstName, LastName);
}

But there’s a much shorter syntax for expressing exactly the same thing (modulo casing of parameter names):

但是,用于表达完全相同的内容的语法要短得多(参数名称的模数框):

public data class Person(string FirstName, string LastName);

This declares the public init-only auto-properties and the constructor and the deconstructor, so that you can write:

这声明了仅用于初始化的公共自动属性以及构造函数反构造函数,所以您可以编写如下代码:

var person = new Person("Scott", "Hunter"); // positional construction
var (f, l) = person;                        // positional deconstruction

If you don’t like the generated auto-property you can define your own property of the same name instead, and the generated constructor and deconstructor will just use that one.

如果您不喜欢生成的自动属性,则可以定义自己的同名属性,使得生成的构造函数和反构造函数将仅使用该属性。


Records and mutation

记录和突变

The value-based semantics of a record don’t gel well with mutable state. Imagine putting a record object into a dictionary. Finding it again depends on Equals and (sometimes) GethashCode. But if the record changes its state, it will also change what it’s equal to! We might not be able to find it again! In a hash table implementation it might even corrupt the data structure, since placement is based on the hash code it has “on arrival”!

记录的基于值的语义与可变状态不能很好地融合在一起。想象一下将记录对象放入字典中。再次找到它取决于Equals和(有时)GethashCode。但是,如果记录更改其状态,则它也将更改其含义!我们可能无法再次找到它!在Hash表的实现中,它甚至可能破坏数据结构,因为放置是基于其“到达时”的Hash值!

There are probably some valid advanced uses of mutable state inside of records, notably for caching. But the manual work involved in overriding the default behaviors to ignore such state is likely to be considerable.

记录内部可能存在对可变状态的一些有效的高级用法,特别是用于缓存。但是,涉及覆盖默认行为以忽略这种状态的手动工作可能非常耗时。

With-expressions and inheritance

with 表达式和继承

Value-based equality and non-destructive mutation are notoriously challenging when combined with inheritance. Let’s add a derived record class Student to our running example:

与继承相结合时,值类型的相等性和非破坏性突变是众所周知的挑战。让Student我们在正在运行的示例中添加一个派生记录类:

public data class Person { string FirstName; string LastName; }
public data class Student : Person { int ID; }

And let’s start our with-expression example by actually creating a Student, but storing it in a Person variable:

让我们开始创建with表达式示例,方法是实际创建一个Student,但将其存储在Person变量中:

Person person = new Student { FirstName = "Scott", LastName = "Hunter", ID = GetNewId() };
otherPerson = person with { LastName = "Hanselman" };

At the point of that with-expression on the last line the compiler has no idea that person actually contains a Student. Yet, the new person wouldn’t be a proper copy if it wasn’t actually a Student object, complete with the same ID as the first one copied over.

在最后一行的with表达式位置,编译器不知道person实际上包含一个Student。但是,如果新的 Person 类型实际上不是Student对象,那么它就不是完全的副本,并且与ID第一个被复制的对象完全相同。(这句有点拗口?)

C# makes this work. Records have a hidden virtual method that is entrusted with “cloning” the whole object. Every derived record type overrides this method to call the copy constructor of that type, and the copy constructor of a derived record chains to the copy constructor of the base record. A with-expression simply calls the hidden “clone” method and applies the object initializer to the result.

C#做到了。记录具有一个隐藏的虚拟方法,该方法委托“克隆” 整个对象。每个派生记录类型都将重写此方法以调用该类型的副本构造函数,而派生记录的副本构造函数将链接到基本记录的副本构造函数。一个with-expression只是调用隐藏的“克隆”的方法和适用对象初始化的结果。


Value-based equality and inheritance

值类型的相等性与继承

Similarly to the with-expression support, value-based equality also has to be “virtual”, in the sense that Students need to compare all the Student fields, even if the statically known type at the point of comparison is a base type like Person. That is easily achieved by overriding the already virtual Equals method.

with表达式支持的方式类似,值类型的相等性也必须是“虚拟的”,即Student需要比较所有Student字段,即使在比较时静态已知的类型是基本类型,例如Person。通过覆盖已经存在的虚拟Equals方法很容易实现。

However, there is an additional challenge with equality: What if you compare two different kinds of Person? We can’t really just let one of them decide which equality to apply: Equality is supposed to be symmetric, so the result should be the same regardless of which of the two objects come first. In other words, they have to agree on the equality being applied!

但是,平等还有另外一个挑战:如果比较两种不同的类型Person怎么办?我们不能真正让他们中的一个决定要应用哪个相等:相等应该是对称的,因此无论两个对象中的哪个首先出现,结果都应该相同。换句话说,他们必须就适用的相等达成一致

An example to illustrate the problem:

一个例子来说明这个问题:

Person person1 = new Person { FirstName = "Scott", LastName = "Hunter" };
Person person2 = new Student { FirstName = "Scott", LastName = "Hunter", ID = GetNewId() };

Are the two objects equal to one another? person1 might think so, since person2 has all the Person things right, but person2 would beg to differ! We need to make sure that they both agree that they are different objects.

这两个对象彼此相等吗?person1也许会这样想,因为person2所有的Person事情都对,person2但愿与众不同!我们需要确保它们都同意它们是不同的对象。

Once again, C# takes care of this for you automatically. The way it’s done is that records have a virtual protected property called EqualityContract. Every derived record overrides it, and in order to compare equal, the two objects musts have the same EqualityContract.

C#再一次自动为您解决此问题。完成的方式是记录具有称为的虚拟受保护属性EqualityContract。每个派生的记录都会覆盖它,并且为了比较相等,两个对象必须具有相同的EqualityContract

Top-level programs

顶层结构编程

Writing a simple program in C# requires a remarkable amount of boilerplate code:

用C#编写一个简单的程序需要大量的样板代码,例如:

using System;
class Program{static void Main(){Console.WriteLine("Hello World!");}
}

This is not only overwhelming for language beginners, but clutters up the code and adds levels of indentation.

这不仅使语言初学者不知所措,而且使代码混乱并增加了缩进级别。

In C# 9.0 you can just choose to write your main program at the top level instead:

在C#9.0中,您可以选择在最顶层编写主程序:

using System;
Console.WriteLine("Hello World!");

Any statement is allowed. The program has to occur after the usings and before any type or namespace declarations in the file, and you can only do this in one file, just as you can have only one Main method today.

允许任何语句。该程序必须在using语句之后并且在文件中任何类型或名称空间声明之前发生,并且您只能在一个文件中执行此操作,就像Main今天只有一种方法一样。

If you want to return a status code you can do that. If you want to await things you can do that. And if you want to access command line arguments, args is available as a “magic” parameter.

如果要返回状态代码,可以执行此操作。如果您想要await做某事,您可以这样做。而且,如果要访问命令行参数,args则可以作为“魔术”参数使用。

Local functions are a form of statement and are also allowed in the top level program. It is an error to call them from anywhere outside of the top level statement p.

局部函数是语句的一种形式,并且在顶层程序中也允许使用。从顶级语句部分之外的任何地方调用它们是错误的。

Improved pattern matching

改进的模式匹配

Several new kinds of patterns have been added in C# 9.0. Let’s look at them in the context of this code snippet from the pattern matching tutorial:

C#9.0中添加了几种新的模式。让我们在模式匹配教程的以下代码片段的上下文中查看它们:

publicstaticdecimalCalculateToll(object vehicle)=>vehicle switch{...DeliveryTruck t when t.GrossWeightClass > 5000 => 10.00m + 5.00m,DeliveryTruck t when t.GrossWeightClass < 3000 => 10.00m - 2.00m,DeliveryTruck _ => 10.00m,_ => throw new ArgumentException("Not a known vehicle type", nameof(vehicle))};


Simple type patterns

简单类型模式

Currently, a type pattern needs to declare an identifier when the type matches – even if that identifier is a discard _, as in DeliveryTruck _ above. But now you can just write the type:

当前,类型模式需要在类型匹配时声明一个标识符,即使该标识符是一个废弃_(如上所述)。但是现在您可以这样编写类型:

DeliveryTruck => 10.00m,

Relational patterns

关系匹配模式

C# 9.0 introduces patterns corresponding to the relational operators <<= and so on. So you can now write the DeliveryTruck part of the above pattern as a nested switch expression:

C#9.0引入了与关系运算符相对应的模式<<=依此类推。因此,您现在可以DeliveryTruck将上述模式的一部分编写为嵌套的switch表达式:

DeliveryTruck t when t.GrossWeightClass switch
{> 5000 => 10.00m + 5.00m,< 3000 => 10.00m - 2.00m,_ => 10.00m,
},

Here > 5000 and < 3000 are relational patterns.

这里和是关系模式是大于5000小于3000

Logical patterns

逻辑匹配模式

Finally you can combine patterns with logical operators andor and not, spelled out as words to avoid confusion with the operators used in expressions. For instance, the cases of the nested switch above could be put into ascending order like this:

最后,您可以用逻辑运算符相结合的模式andor并且not,阐述了作为的话,以避免在表达式中使用操作者的困惑。例如,上面的嵌套开关的情况可以按如下升序排列:

DeliveryTruck t when t.GrossWeightClass switch
{< 3000 => 10.00m - 2.00m,>= 3000 and <= 5000 => 10.00m,> 5000 => 10.00m + 5.00m,
},

The middle case there uses and to combine two relational patterns and form a pattern representing an interval.

中间情况and用来组合两个关系模式并形成表示间隔的模式。

A common use of the not pattern will be applying it to the null constant pattern, as in not null. For instance we can split the handling of unknown cases depending on whether they are null:

模式的常见用法是not将其应用于null恒定模式,如代码中所示。例如,我们可以根据未知案例是否为空来拆分处理方式:not null

not null => throw new ArgumentException($"Not a known vehicle type: {vehicle}", nameof(vehicle)),
null => throw new ArgumentNullException(nameof(vehicle))

Also not is going to be convenient in if-conditions containing is-expressions where, instead of unwieldy double parentheses:

not在包含is表达式的if条件中,代替笨重的双括号,以前这样写:

if (!(e is Customer)) { ... }

You can just say

现在可以这么写

if (e is not Customer) { ... }


Improved target typing

改进了目标类型(创建方式)

“Target typing” is a term we use for when an expression gets its type from the context of where it’s being used. For instance null and lambda expressions are always target typed.

“目标类型”是当表达式从其使用位置的上下文中获取其类型时使用的术语。例如null,lambda表达式始终是目标类型。

In C# 9.0 some expressions that weren’t previously target typed become able to be guided by their context.

在C#9.0中,某些以前不是目标类型的表达式可以通过其上下文进行引导。

Target-typed new expressions

创建目标类型的new表达式

new expressions in C# have always required a type to be specified (except for implicitly typed array expressions). Now you can leave out the type if there’s a clear type that the expressions is being assigned to.

C#中的new表达式创建对象始终要求指定类型(隐式类型的数组表达式除外)。现在,如果有一个明确的类型要分配给表达式,则可以省去该类型。

Point p = new (3, 5);


Target typed ?? and ?:

目标类型??和?:

Sometimes conditional ?? and ?: expressions don’t have an obvious shared type between the branches. Such cases fail today, but C# 9.0 will allow them if there’s a target type that both branches convert to:

有时条件???:表达式在分支之间没有明显的共享类型。这种情况现在不允许,但是如果两个分支都转换为以下目标类型,则C#9.0将允许它们:

Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type


Covariant returns

返回值协变

It’s sometimes useful to express that a method override in a derived class has a more specific return type than the declaration in the base type. C# 9.0 allows that:

表达派生类中的方法重写比基类型中的声明更具体的返回类型有时是有用的。C#9.0允许:

abstract class Animal
{public abstract Food GetFood();...
}
class Tiger: Animal
{public override Meat GetFood()=> ...;
}

And much more…

还有更多…

The best place to check out the full set of upcoming features for C# 9.0 and follow their completion is the Language Feature Status on the Roslyn (C#/VB Compiler) GitHub repo.

在Roslyn(C#/ VB编译器)GitHub存储库上,查看C#9.0即将推出的全部功能并完成这些功能的最佳场所。

 

原文:https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/

推荐阅读:

  • [翻译] .NET 官宣跨平台 UI 框架 MAUI

  • Orleans 3.0 为我们带来了什么

  • 让.NetCore程序跑在任何有docker的地方

  • .NET 开源项目 Anet 介绍

  • .NET 开源项目 Polly 介绍

开发者精选资讯

每日为您推荐开发精选资讯


长按二维码 关注「开发者精选资讯」公众号

好文章,我在看❤️

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

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

相关文章

操作系统第四章习题

操作系统第四章习题 1.对一个将页表放在内存中的分页系统&#xff1a; (1) 如果访问内存需要0.2μs&#xff0c;有效访问时间为多少? (2) 如果加一快表&#xff0c;且假定在快表中找到页表的几率高达90%&#xff0c;则有效访问时间又是多少&#xff08;假定查快表需花的时间…

[C++11]右值和右值引用

代码如下: #include <iostream> using namespace std;int main() {//左值int num 9;//左值引用int &a num;//右值const int N 5;//右值引用int && b 8;//常量左值引用const int &c num;//常量右值引用const int &&d 6;//const int &&…

我们为什么推荐在Json中使用string表示Number属性值

在这篇简短的文章中&#xff0c;我将解释在使用JSON传输数据时&#xff0c;为什么浮点数或大十进制值应表示为字符串 。long类型引发的诡异情况长话短说&#xff0c;同事在利用swagger对接后端API时&#xff0c;诡异的发现swaggerUI中显示的json属性值并不是api返回的值。[Http…

并查集+基础知识点详解

并查集概念 并查集单看名字大家也能猜到这个算法的作用&#xff0c;是用来对集合进行合并和查找操作 并查集是一种树型的数据结构&#xff0c;用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。——来自百度百科 就是将原本不一样的集合&#xff0c;但是由于某种关系有…

[C++11]move资源的转移

从实现上讲&#xff0c;std::move 基本等同于一个类型转换&#xff1a;static_cast<T&&>(lvalue);&#xff0c;函数原型如下: template<class _Ty> _NODISCARD constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) _NOEXCEPT { …

基于 abp vNext 和 .NET Core 开发博客项目 - 统一规范API,包装返回模型

上一篇文章使用自定义仓储完成了简单的增删改查案例&#xff0c;有心的同学可以看出&#xff0c;我们的返回参数一塌糊涂&#xff0c;显得很不友好。在实际开发过程中&#xff0c;每个公司可能不尽相同&#xff0c;但都大同小异&#xff0c;我们的返回数据都是包裹在一个公共的…

奔小康赚大钱 HDU - 2255( 二分图匹配KM算法详解)

题目 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革&#xff1a;重新分配房子。 这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住&#xff08;如果有老百姓没房子住的话&#xff0c;容易引起不安定因素&…

记一次排查线上程序内存的忽高忽低,又是大集合惹祸了

一&#xff1a;背景1. 讲故事昨天继续还技术债&#xff0c;优化一轮后的程序拉到线上后内存继续忽高忽低&#xff0c;低的时候20G&#xff0c;高的时候30G&#xff0c;过了一会又下降了几个G&#xff0c;毫无疑问&#xff0c;程序中有什么集合或者什么操作占用了大量内存&#…

[C++11]forward完美转发

// 函数原型 template <class T> T&& forward (typename remove_reference<T>::type& t) noexcept; template <class T> T&& forward (typename remove_reference<T>::type&& t) noexcept;// 精简之后的样子 std::forward…

Pipe HDU - 2150(判断线段相交+向量叉乘线代详解)

题目&#xff1a; 经过激烈的争夺&#xff0c;Lele终于把那块地从Yueyue的手里抢了回来。接下来&#xff0c;Lele要开始建造他的灌溉系统。 通过咨询Lele的好友——化学系的TT&#xff0c;Lele决定在田里挖出N条沟渠&#xff0c;每条沟渠输送一种肥料。 每条沟渠可以看作是一…

win7如何将计算机移至桌面,如何将win7电脑桌面的文件转移到其他盘中?

想必很多朋友都和小编一样&#xff0c;是一个嫌麻烦的人&#xff0c;是一个不怎么爱收拾的人吧?这种人有一个通病&#xff0c;那就是喜欢将一些重要的文件放置在win7 64位纯净版下载的桌面上&#xff0c;这样的话&#xff0c;不仅容易找到&#xff0c;而且方便使用&#xff0c…

凸包算法知识总结

首先&#xff0c;什么是凸包&#xff1f; 假设平面上有p0~p12共13个点&#xff0c;过某些点作一个多边形&#xff0c;使这个多边形能把所有点都“包”起来。当这个多边形是凸多边形的时候&#xff0c;我们就叫它“凸包”。 处理何种问题&#xff1a;凸包可以看成在木板上钉许多…

[C++11]shared_ptr使用的注意事项(内存被重复析构,内存泄漏问题)

shared_ptr使用的注意事项: 1.不能使用一个原始地址初始化多个共享智能指针 2.函数不能返回管理了this的共享智能指针对象 3.共享智能指针不能循环引用 不能使用一个原始地址初始化多个共享智能指针 代码如下: #include <iostream> #include <memory> using name…

一文解读使用WinDbg排查iis 中CPU占用高的站点问题

一、概述在Window服务器部署程序后&#xff0c;可能因为代码的不合理或者其他各种各样的问题&#xff0c;会导致CPU暴增&#xff0c;甚至达到100%等情况&#xff0c;严重危及到服务器的稳定以及系统稳定&#xff0c;但是一般来说对于已发布的程序&#xff0c;没法即时看到出问题…

Power Network POJ - 1459(EK算法模板+详解)

题意&#xff1a; 总共有a个节点&#xff0c;其中有发电站b个、用户c个和调度器a-b-c个三种节点&#xff0c;每个发电站有一个最大发电量&#xff0c;每个用户有个最大接受电量&#xff0c;现在有d条有向边&#xff0c;边有一个最大的流量代表&#xff0c;最多可以流出这么多电…

[C++11]shared_ptr共享智能指针的初始化与使用

使用智能指针需要添加头文件: 代码如下: #include <memory>shared_ptr使用的注意事项: 1.不能使用一个原始地址初始化多个共享智能指针 2.函数不能返回管理了this的共享智能指针对象 3.共享智能指针不能循环引用 初始化: 1.通过构造函数初始化 代码如下: std::shar…

人在职场,表达似水

最近几天集中在和部门内的小伙伴做1&#xff1a;1Talk。发现有不少人表达能力真的不是很好&#xff0c;而且水平长期停滞不前。现场与他们分享了一些我的经验&#xff0c;趁热打铁也想在这里分享给大家。表达能力不好本身就是做技术的人身上的一个常见标签。如果仅仅是标签也就…

[C++11]弱引用智能指针weak_ptr初始化和相关的操作函数

弱引用智能指针 std::weak_ptr 可以看做是 shared_ptr 的助手&#xff0c;它不管理 shared_ptr 内部的指针。std::weak_ptr 没有重载操作符 * 和 ->&#xff0c;因为它不共享指针&#xff0c;不能操作资源&#xff0c;所以它的构造不会增加引用计数&#xff0c;析构也不会减…

电子科技大学计算机网络技术专业,计算机专业前景如何?最强十大高校有哪些?电子科大排名多少?...

近几年计算机专业以及与计算机相关的专业可谓是火的不能再火&#xff0c;越来越多的考生在高考时选择了计算机专业或者与计算机相关的专业&#xff01;事实也是如此&#xff0c;随着科技的进步&#xff0c;信息技术的迅猛发展&#xff0c;特别是计算机技术的发展&#xff0c;以…