Was ist neu in C # 8?

Der G8 hat noch nicht einmal RTM veröffentlicht und ich schreibe bereits einen Beitrag darüber. Warum? Nun, die Hauptidee ist, dass derjenige, der gewarnt wird, bewaffnet ist. In diesem Beitrag geht es also um das, was derzeit bekannt ist, und wenn es sich um ein Setup handelt, dann zu Recht.



Nullable Referenztypen


, , «» . — , NULL nullptr ++. — zero-terminated strings, (n). null.


C# , :


public class Person
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string MiddleName { get; set; }
  public Person(string first, string last, string middle) =>
    (FirstName, LastName, MiddleName) = (first, last, middle);
  public string FullName =>
    $"{FirstName} {MiddleName[0]} {LastName}";
}

. , , . C# null. ($ string.Format()), . null-, NRE (NullReferenceException).


, .. null, 100500 . Optional , , .


- , . (NuGet JetBrains.Annotations) :


public class Person
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  [CanBeNull] public string MiddleName { get; set; }
  public Person(string first, string last, [CanBeNull] string middle) =>
    (FirstName, LastName, MiddleName) = (first, last, middle);
  public string FullName =>
    $"{FirstName} {MiddleName[0]} {LastName}";
}

NRE MiddleName[0].




Microsoft… , . , VS . . .


, . , . , C#8 :


#nullable enable

. , -


var p = new Person("Dmitri", "Nesteruk", null);

warning:

1>NullableReferenceTypes.cs(26,48,26,52): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.

-, , ( treat warnings as errors ).


, ? - - C#, MiddleName null [0] .


:


public string? MiddleName;

, ? - string? Nullable<T>, , T : struct, - . — , .. string.


. - , :


public string FullName =>  $"{FirstName} {MiddleName?[0]} {LastName}";

: IL? — ! : nullable nullable [Nullable]. : .



C#8 - -. , nullable-


string? s = GetString();

warning. :


if (s != null){  char c = s[0];}

! , . .



null. — «», , null- .


— . :


  • (null as Person).FullName warning

  • (null as Person)!.FullName warning , ..

  • (null as Person)!!!!!!!!!!!!!.FullName

  • (null as Person)!?.FullName null; , ?!,



, - BCL .


Type t = Type.GetType("abracadabra");Console.WriteLine(t.Name);

. - Type.GetType() null , BCL nullable , .


, «»


Type t = Type.GetType("abracadabra");
Type? u = t;
Console.WriteLine(u.Name);

. , t != null, u null, .



Nullable reference types — , . . , , - nullability , , .



: , , , . , X~N(0,1), E[X²] V[X²]?


, , « ».


, : Index Range.


Index


, int uint? : ( ). , C# x[-1] .


. .. -1 , , .


C# . , . , Index , :


Index i0 = 2; // implicit conversion

, , .


Index ( — ):


  • Value,

  • IsFromEnd — , ,


:


Index i1 = new Index(0, false);

, , . ( , ) :


var i2 = ^0; // Index(0, true)

! , ^ ( , LaTeX, ), « ».


, , (operator this[]) Index,


var items = new[] { 1, 2, 3, 4, 5 };
items[^2] = 33; // 1, 2, 33, 4, 5

Range


Range, , , 1. :


X..Y

« X Y». , YY. .


, :


  • var a = i1..i2; // Range(i1, i2)

  • var b = i1..; // Range(i1, new Index(0, true));i1

  • var c = ..i2; // Range(new Index(0, false), i2)i2

  • var e = ..; — ,

  • Range.ToEnd(2); — — , ; , dotPeek, ilSpy


?


, ++ (undefined behavior?). , Range C# . : « ».


x = {1, 2, 3}. x[0..2] {1, 2}, x[..2] x[..], {1, 2, 3}.


.. x[2] x[^1] — , Range- !



-, X..Y X <= Y ( ?). ( 7..3), ArgumentOutOfRangeException. .. , .


-, «» , 1..2..100 . . MATLAB.


Range :


  • , ,

  • Substring(). C# .

  • AsSpan() Range.

  • Span RangeSpan.Slice(), -.


, Index/Range operator this[]. , « » . , (singly linked list), - « » — .



, struct-. - , «» , .


, :




Default Interface Members


, . , — ?


. Enumerable.Count()while (x.MoveNext()) , . Count() :


if (x is IList<T> list)
  return list.Count;

? IReadOnlyList<T>, ? « »?!?


, , open-closed principle SOLID, .. — .


? , , , - Count(), IReadOnlyList<T>, , . ! - IReadOnlyList<T>.Count() IEnumerable<T>.Count()? , ! .


. , - -, .



:


public interface IHuman
{
  string Name { get; set; }
    
  public void SayHello() 
  {
    Console.WriteLine($"Hello, I am {Name}");
  }
}

public class Human : IHuman
{
  public string Name { get;set; }
}

, , :


Human human = new Human() { Name = "John" };
human.SayHello(); // will not compile

? , . — , , , .


, ? , , , . Human SayHello()? , .


: , :


IHuman human = new Human() { Name = "John" };
human.SayHello();
((IHuman)new Human { … }).SayHello();


, , : Foo() ( ), Foo(), :


public interface IHuman
{
  string Name { get; set; }
  
  void SayHello() 
  {
    Console.WriteLine($"Hello, I am {Name}");
  }
}
public interface IFriendlyHuman : IHuman
{
  void SayHello()
  {
    Console.WriteLine(      $"Greeting, my name is {Name}");
  }
}
((IHuman)new Human()).SayHello();
// Hello, I am John
((IFriendlyHuman)new Human()).SayHello();
// Greeting, my name is John

, IFriendlyHuman.SayHello() override- IHuman.SayHello(), ! SayHello() ? :


public interface IFriendlyHuman : IHuman
{
  void IHuman.SayHello()
  //   ↑↑↑↑↑↑
  {
    Console.WriteLine(      $"Greeting, my name is {Name}");
  }
}

SayHello() , IHuman IFriendlyHuman , :


((IHuman)new Human()).SayHello();
Greeting, my name is John
((IFriendlyHuman)new Human()).SayHello();
Greeting, my name is John

Diamond Inheritance


, « override-» - , :


interface ITalk { void Greet(); }
interface IAmBritish : ITalk
{
  void ITalk.Greet() => WriteLine("Good day!");
}
interface IAmAmerican : ITalk
{
  void ITalk.Greet() => WriteLine("Howdy!");
}
class DualNational : IAmBritish, IAmAmerican {}
// Error CS8705 Interface member 'ITalk.Greet()' does not have a most specific implementation. Neither 'IAmBritish.ITalk.Greet()', nor 'IAmAmerican.ITalk.Greet()' are most specific.

, « » ( , ) , , - - IAmAmerican.Greet() — , -, ?



. , , , API. — -. -?


Pattern Matching


F# . — F# , , # , .


, F# match # switch. C#8 .


Property Matching


, :


struct PhoneNumber{
  public int Code, Number;
}
var phoneNumber = new PhoneNumber();
var origin = phoneNumber switch {
  { Number: 112 } => "Emergency",
  { Code: 44 } => "UK"
};

phoneNumber, . switch statement switch expression, - .


, — , . : default-init ( , default(T) ) . , , :




:





, , :


var origin = phoneNumber switch {
  { Number: 112 } => "Emergency",
  { Code: 44 } => "UK",
  { } => "Indeterminate",
  _ => "Missing"
};

? , 2 : _ (), , {} null.


, . ?


var origin = phoneNumber switch {
  { Number: 112 } => "Emergency",
  { Code: 44 } => "UK",
  { } => "Unknown"
};

? phoneNumber struct — , class. - , null, … nullable reference types!


, .



- , . nullable reference types — , nullable , recursive patterns — .


F#, , . C# , , , C# — .


, « » C# -, :


var personsOrigin = person switch {
  { Name: "Dmitri" } => "Russia",
  { PhoneNumber: { Code: 46 } } => "Sweden",
  { Name: var name } => $"No idea where {name} lives"
};

. — , person.PhoneNumber Code 46. — . , «».



: switch-. :


var error = person switch {
  null => "Object missing",
  { PhoneNumber: null } => "Phone number missing entirely",
  { PhoneNumber: { Number: 0 } } => "Actual number missing",
  { PhoneNumber: { Code: var code } } when code < 0 => "WTF?",
  { } => null // no error
};
if (error != null)
  throw new ArgumentException(error);

, : , when , .



- «» . , :


IEnumerable<int> GetMainOfficeNumbers()
{
  foreach (var pn in numbers)
  {
    if (pn is ExtendedPhoneNumber { Office: "main" })
      yield return pn.Number;
  }
}

, , . .



— , , . Deconstruct() out-.


, - :


var type = shape switch
{
  Rectangle((0, 0), 0, 0) => "Point at origin",
  Circle((0, 0), _) => "Circle at origin",
  Rectangle(_, var w, var h) when w == h => "Square",
  Rectangle((var x, var y), var w, var h) =>
    $"A {w}×{h} rectangle at ({x},{y})",
  _ => "something else"
};

, : -, , . «» — , . (_) , .



, . .



, ? , , -. . . , VS 2019 Preview (-, preview RTM), .NET Core 3 ( .NET Framework), dotPeek , .


. () . ■

Source: https://habr.com/ru/post/de454446/


All Articles