
Todas as ferramentas introduzidas anteriormente nas versões secundárias do C # foram projetadas para não alterar muito o idioma. São mais como aprimoramentos de sintaxe e pequenas adições aos novos recursos do C # 7.0 .
Essa abordagem foi deliberada e permanece válida.
Mudanças mais sérias, que exigem mais trabalho em todas as etapas do desenvolvimento (design, implementação e teste), continuarão a ser lançadas apenas nas principais versões do idioma. Embora a versão menor final do C # 7 ainda não tenha sido lançada, a equipe já está trabalhando ativamente na próxima versão principal do idioma: C # 8.0.
Neste artigo, pretendo apresentar uma seleção de recursos atualmente planejados que provavelmente estarão no release final. Todos eles estão em um estágio inicial de desenvolvimento e estão sujeitos a alterações.
Tipos de referência anuláveis
Essa ferramenta já foi oferecida nos estágios iniciais do desenvolvimento do C # 7.0, mas foi atrasada até a próxima versão principal. Seu objetivo é ajudar o desenvolvedor a evitar NullReferenceException sem tratamento.
A idéia principal é permitir que você especifique ao determinar o tipo de uma variável se ela pode ser nula ou não:
IWeapon? canBeNull;
IWeapon cantBeNull;
null , null -null , ( , , ):
canBeNull = null;       //  
cantBeNull = null;      // 
cantBeNull = canBeNull; // 
, nullable- null:
canBeNull.Repair();       // 
cantBeNull.Repair();      //  
if (canBeNull != null) {
    cantBeNull.Repair();  //  
}
, : , null. , null- .
nullability , . , .
Visual Studio 2017 15.6 update.
Records
, - C# , -.
:
public class Sword(int Damage, int Durability);
:
public class Sword : IEquatable<Sword>
{
    public int Damage { get; }
    public int Durability { get; }
    public Sword(int Damage, int Durability)
    {
        this.Damage = Damage;
        this.Durability = Durability;
    }
    public bool Equals(Sword other)
    {
        return Equals(Damage, other.Damage) 
            && Equals(Durability, other.Durability);
    }
    public override bool Equals(object other)
    {
        return (other as Sword)?.Equals(this) == true;
    }
    public override int GetHashCode()
    {
        return (Damage.GetHashCode() * 17 + Durability.GetHashCode());
    }
    public void Deconstruct(out int Damage, out int Durability)
    {
        Damage = this.Damage;
        Durability = this.Durability;
    }
    public Sword With(int Damage = this.Damage, int Durability 
        = this.Durability) => new Sword(Damage, Durability);
}
, , . GetHashCode - Dictionary Hashtable. Deconstruct :
var (damage, durability) = sword;
, , , . , , . , , With, :
var strongerSword = sword.With(Damage: 8);
, :
var strongerSword = sword with { Damage = 8 };
Recursive Patterns
C# 7.0. 8.0 :
. Deconstruct():
if (sword is Sword(10, var durability)) {
    //  ,  Damage = 10
    // durability   sword.Durability
}
(tuple) :
switch (state, transition)
{
    case (State.Running, Transition.Suspend):
        state = State.Suspended;
        break;
}
switch , . , :
state = (state, transition) switch {
    (State.Running, Transition.Suspend) => State.Suspended,
    (State.Suspended, Transition.Resume) => State.Running,
    (State.Suspended, Transition.Terminate) => State.NotRunning,
    (State.NotRunning, Transition.Activate) => State.Running,
    _ => throw new InvalidOperationException()
};
Default Interface Methods
, C# , :
interface ISample
{
    void M1();                                    // 
    void M2() => Console.WriteLine("ISample.M2"); // 
}
, :
abstract class SampleBase
{
    public abstract void M1();
    public void M2() => Console.WriteLine("SampleBase.M2");
}
, C# 8 , . , .
. , . , . , . , .
C#, .
, . , – trait .
, , . C# 8.0 , :
Asynchronous Streams
C# . C# 8.0, . IEnumerable IEnumerator:
public interface IAsyncEnumerable<out T>
{
    IAsyncEnumerator<T> GetAsyncEnumerator();
}
public interface IAsyncEnumerator<out T> : IAsyncDisposable
{
    Task<bool> MoveNextAsync();
    T Current { get; }
}
, IDisposable:
public interface IAsyncDisposable
{
    Task DisposeAsync();
}
:
var enumerator = enumerable.GetAsyncEnumerator();
try
{
    while (await enumerator.WaitForNextAsync())
    {
        while (true)
        {
            Use(enumerator.Current);
        }
    }
}
finally
{
    await enumerator.DisposeAsync();
}
– , while(true). - , . , , . , , .
, . , foreach. :
foreach await (var item in enumerable)
{
    Use(item);
}
, foreach , .
, yield. , :
async IAsyncEnumerable<int> AsyncIterator()
{
    try
    {
        for (int i = 0; i < 100; i++)
        {
            yield await GetValueAsync(i);
        }
    }
    finally
    {
        await HandleErrorAsync();
    }
}
LINQ.
Ranges
:
var range = 1..5;
, :
struct Range : IEnumerable<int>
{
    public Range(int start, int end);
    public int Start { get; }
    public int End { get; }
    public StructRangeEnumerator GetEnumerator();
    // overloads for Equals, GetHashCode...
}
:
Span<T> this[Range range]
{
    get
    {
        return ((Span<T>)this).Slice(start: range.Start, 
            length: range.End - range.Start);
    }
}
foreach (var index in min..max)
{
    //  
}
switch (value)
{
    case 1..5:
        //   
        break;
}
step – , . – ( ). Python, .
, , .., . , .
, , , ..:
a[start:end] #   start  end-1
a[:end]      # items    end-1
, .
Generic Attributes
. , , :
public class TypedAttribute : Attribute
{
    public TypedAttribute(Type type)
    {
        // ...
    }
}
, :
public class TypedAttribute<T> : Attribute
{
    public TypedAttribute()
    {
        // ...
    }
}
, , :
public TypedAttribute(T value)
{
    // ...
}
Default Literal in Deconstruction
C# 7, :
(int x, int y) = (default, default);
default, :
(int x, int y) = default;
Caller Argument Expression
C# 5, CallerMemberName, CallerFilePath CallerLineNumber) .
CallerMemberName INotifyPropertyChanged:
class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    private int property;
    public int Property
    {
        get { return property; }
        set
        {
            if (value != property)
            {
                property = value;
                OnPropertyChanged();
            }
        }
    }
}
C# 8 CallerArgumentExpression, , :
public Validate(int[] array, [CallerArgumentExpression("array")] string arrayExpression = null)
{
    if (array == null)
    {
        throw new ArgumentNullException(nameof(array), $"{arrayExpression} was null.");
    }
    if (array.Length == 0)
    {
        throw new ArgumentException($"{arrayExpression} was empty.", nameof(array));
    }
}
, , .
Target-typed new Expression
, var ( ) :
Dictionary<string, string> dictionary = new Dictionary<string, string>(); //  var
var dictionary = new Dictionary<string, string>(); //  var
(), , :
class DictionaryWrapper
{
    private Dictionary<string, string> dictionary = new Dictionary<string, string>();
    // ...
}
C# 8, new, :
class DictionaryWrapper
{
    private Dictionary<string, string> dictionary = new();
    // ...
}
, , . , .
Ordering of ref and partial Modifiers on Type Declarations
C# , partial struct class.
ref C# 7.2, partial , , ref struct, partial partial, .
, :
public ref struct NonPartialStruct { }
public ref partial struct PartialStruct { }
C# 8, , :
public partial ref struct PartialStruct { }
C# 8 . .
, C# 8.0, . , , . , , .
, , . .
C# 7.1, 7.2 and 7.3 — New Features (Updated).
, C#. C# — - ? , :
- var . . . , .
- Go . . -. , , ( ) .
- C# . ( .Net Framework 1.1), ( «» LINQ – , SQL, ). , .
- - typedef, , , (var ). new(), ( ).
, , . GO C# . , . C# , – .
? . . C# – Common Language Infrastructure (CLI). CLI , , . Java/Kotlin. , ?
( Nullable Reference Types). , .