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
( — ):
:
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». , Y
— Y
. .
, :
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
:
, 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 , .
. () . ■