Záznam ze Vzdělávacího okénka HAVIT ze 28. března 2019, kde Jiří Činčura povídal o ref returns v C#.
Tentokrát v angličtině pro lepší zapojení našich zahraničních pracovníků.
Záznam ze Vzdělávacího okénka HAVIT ze 28. března 2019, kde Jiří Činčura povídal o ref returns v C#.
Tentokrát v angličtině pro lepší zapojení našich zahraničních pracovníků.
Záznam ze Vzdělávacího okénka HAVIT z 21. února 2019, kde jsem ukazoval chystané novinky v C# 8.0:
Nahrávka je publikována na našem HAVIT YouTube Channelu.
Záznam ze Vzdělávacího okénka HAVIT ze 14. února 2019, kde Jirka Kanda povídal o tuplech, deconstruction a jejich použití pro vícenásobné návratové hodnoty z metod.
Nahrávka je publikována na našem HAVIT YouTube Channelu.
Záznam z mého vystoupení pro ShowIT Bratislava ze 5. února 2019.
Slides a dema:
Dotčená témata:
Nahrávka je publikována na našem HAVIT YouTube Channelu.
Záznamy stejné přednášky z konferencí G2B TechEd Brno a ShowIT Bratislava.
Brněnská verze z 30.1.2018 se musela vmáčknout do 45 minut:
Bratislavská verze z 31.1.2018 měla prostor 70 minut:
Záznamy jsou uloženy na našem HAVIT YouTube Channelu.
Slides, dema a záznam z mé přednášky pro TechEd DevCon Praha ze 17.5.2017:
Záznam z přednášky je publikován na našem HAVIT YouTube Channel.
Dotčená témata
Slides, dema a záznam z mé přednášky pro TechEd DevCon Praha z 15.5.2017:
Záznam z přednášky je publikován na našem HAVIT YouTube Channel.
Dotčená témata
[DataRow]throw expressionsout variablesValueTask<>Možnost deklarovat out-proměnné inline při volání metod:
// dříve int x; if (int.TryParse(s, out x)) ... // C# 7.0 if (int.TryParse(s, out int x)) ... // C# 7.0 if (int.TryParse(s, out var x)) ...
…rozhodně přehlednější zápis.
Možnost vytvářet lehké datové struktury s několika fieldy a používat je i jako návratové hodnoty metod:
private static (int Max, int Min) Range(IEnumerable<int> numbers)
{
int min = int.MaxValue;
int max = int.MinValue;
foreach(var n in numbers)
{
min = (n < min) ? n : min;
max = (n > max) ? n : max;
}
return (max, min);
}
var result = Range(numbers);
Console.Write($"{result.Min} - {result.Max}");
(int max, int min) = Range(numbers); // deconstruction
Bude zneužíváno lenochy, co nechtějí psát malé ViewModely, ale budou raději riskovat zmatky při deconstruction (záleží na pořadí prvků, ne názvech!).
Možnost definovat pomocné lokální funkce uvnitř metod:
public IEnumerable<MyClass> GetActiveItems()
{
var rawData = myClassDataService.GetPrimaryItems().Where(i => IsActive(i));
if (!rawData.Any())
{
return myClassDataService.GetSecondaryItems().Where(i => IsActive(i));
}
return rawData;
bool IsActive(MyClass item)
{
return (item.State == States.Active) && (item.Rows.Any());
}
}
Dosud bylo možné použít anonymní lambda výrazy, syntaxe je však nyní trochu přívětivější. Zde například chci 2x vyhodnotit stejnou podmínku IsActive, ale z jiné metody ve třídě to nepotřebuji a lokální funkce je tak pro mě přehlednější, než samostatná privátní metoda.
Možnost pomocí klíčových slov is a switch řídit větvení kódu, popř. s možností dodatečných podmínek when:
public static int SumTree(IEnumerable<object> values)
{
var sum = 0;
foreach(var item in values)
{
if (item is int val)
sum += val; // leaf-node
else if (item is IEnumerable<object> subList)
sum += SumTree(subList);
}
return sum;
}
public static void SwitchPattern(object o)
{
switch (o)
{
case null:
Console.WriteLine("pattern pro konstantu");
break;
case int i:
Console.WriteLine("Je to číslo!");
break;
case Person p when p.FirstName.StartsWith("Ka"):
Console.WriteLine($"Jméno začíná na Ka: {p.FirstName}");
break;
case Person p:
Console.WriteLine($"Jiné jméno: {p.FirstName}");
break;
case var x:
Console.WriteLine($"jiný typ: {x?.GetType().Name} ");
break;
default:
break;
}
}
Je to podobné, jako C# 6 přišel s podmínkami u catch-bloků. Při if-is testech na typ se bude hodit.
Možnost použít referenci na proměnnou definovanou jinde:
public ref int Find(int number, int[] numbers)
{
for (int i = 0; i < numbers.Length; i++)
{
if (numbers[i] == number)
{
return ref numbers[i]; // vrať referenci, nikoliv hodnotu
}
}
throw new IndexOutOfRangeException($"{nameof(number)} nenalezeno");
}
int[] array = { 1, 15, -39, 0, 7, 14, -12 };
ref int place = ref Find(7, array); // vrátí referenci na pozici se sedmičkou
place = 9; // nahradí v poli nalezenou sedimičku devítkou
WriteLine(array[4]); // vypíše 9
Využití je celkem specifické, ale výjimečně se může hodit.
// Expression-bodied constructor
public ExpressionMembersExample(string label) => this.Label = label;
// Expression-bodied finalizer
~ExpressionMembersExample() => Console.Error.WriteLine("Finalized!");
private string label;
// Expression-bodied get / set accessors.
public string Label
{
get => label;
set => this.label = value ?? "Default label";
}
…snad jedině u jednoduchých properties to zlepšuje čitelnost, jinak nejsem moc velkým příznivcem expression-bodies members.
Hodí se třeba v kombinaci s exression-bodied members:
public string Name
{
get => name;
set => name = value ?? throw new ArgumentNullException();
}
Task<T> je referenční datový typ a jeho použití znamená alokaci objektu na haldě. Pro hodnotové návratové typy nově přichází optimalizace v podobě ValueTask<T>…
public async ValueTask<int> Func()
{
await Task.Delay(100);
return 5;
}
public const int One = 0b0001; // binární číslo public const int Sixteen = 0b0001_0000; // oddělovač (lze použít kdekoliv, ignoruje se) public const long HodneMoc = 100_000_000_000; public const double AvogadroConstant = 6.022_140_857_747_474e23;
…binární zápis se může hodit na flagy, oddělovač na velká čísla.
Do C# 6.0 se dostaly ještě dvě „drobotiny“, které většině vývojářů život nijak zásadně nezmění.
V C# 5.0, v inicializaci kolekcí, nemohla být použita extension-podoba metody Add(), přestože VB.NET toto měl. Byl to spíše bug/opomenutí. Každopádně nyní je to napraveno.
Drobná vylepšení, kterých si málokdo všimne. O něco málo méně míst, kde se můžete setkat s výtkou kompilátoru ohledně nejednoznačnosti volby overloadu (např. u nullable hodnotových typů parametrů, atp.)
Tato úprava jazyka není součástí C# 6.0 RTM, byla odstaněna.
C# 5.0 nedovoluje vytvořit na struct explicitní constructor bez parametrů, hodnoty fieldů jsou totiž automaticky inicializovány svými default(T) hodnotami. C# 6.0 toto omezení odstraňuje:
struct Person
{
public string Name { get; }
public int Age { get; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
public Person() : this("Jane Doe", 37)
{ }
}
Důležitým omezením však je, že takový konstruktor se použije pouze v případě explicitního volání new Person(), zatímco default(Person) stále založí výchozí hodnoty fieldů, stejnětak vytvoření pole new Person[..].