📜 ⬆️ ⬇️

What's new in C # 8?

The “Eight” has not even released RTM, and I am already writing a post about it. What for? Well, the basic idea is that the one who is warned is armed. So in this post it will be about what is known at the moment, and if this is all a setup, well, rightly so.



Nullable Reference Types


, , «» . — , 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- .


— . :




, - 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 ( — ):



:


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. .


, :



?


, ++ (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 :



, 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/454446/


All Articles