Tag Archives: VS2017

ASP.NET Core: Duplicate ‚Content‘ items were included. The .NET SDK includes ‚Content‘ items from your project directory by default.

Pokud dostanete na ASP.NET Core projektu ve Visual Studiu hlášku o duplicitním Contentu:

Error Duplicate ‚Content‘ items were included. The .NET SDK includes ‚Content‘ items from your project directory by default. You can either remove these items from your project file, or set the ‚EnableDefaultContentItems‘ property to ‚false‘ if you want to explicitly include them in your project file. For more information, see https://aka.ms/sdkimplicititems. The duplicate items were: ‚wwwroot\Index.html‘ Web C:\Program Files\dotnet\sdk\1.1.0\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.Sdk.DefaultItems.targets 188

…jedná se o nadrbaný .csproj a pomůže odebrat a přidat složky wwwroot z projektu:

  1. Solution Explorer – pravým na ~/wwwroot – Exclude From Project
  2. zapnout si viditelnost excludovaných souborů – Solution Explorer – Show All Files (jedna z ikonek nahoře)
  3. Solution Explorer – pravým na ~/wwwroot – Include in Project

Novinky ve VS2017 a C# 7.0 – slides, dema a záznam [TechEd Praha 05/2017]

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

  • VS 2017 Novinky
    • Go to All… (Naviagate to…)
    • IntelliSense
    • Find All References
    • Structure Guides
    • Live Unit Testing
    • Installer
    • Debugging – Run to Click
    • Debugging – Exception Helper (NullReferenceException)
  • MSTest v2 [DataRow]
  • Novinky C# 7.0
    • Binary Literals
    • Digit Separators
    • Expression Bodied Members – Constructors, Destructors (Finalizers), Property Accessors
    • throw expressions
    • out variables
    • Tuples
    • Local Functions
    • Pattern Matching
    • ValueTask<>
    • Ref Return, Ref Local

C# 7.0 – Rychlý přehled novinek

Out variables

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.

Tuples

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

Lokální funkce

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.

Pattern matching

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.

Ref locals and returns

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.

Další expression-bodied members

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

Vyhazování výjimek z výrazů

Hodí se třeba v kombinaci s exression-bodied members:

public string Name
{
    get => name;
    set => name = value ?? throw new ArgumentNullException();
}

ValueTask pro async

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;
}

Čitelnější možnosti zápisu číselných konstant

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.

VS2017 #NoResharper Challenge: Navigace Ctrl+T, [něco]+T

Klíčovou funkcí Resharperu pro mě byla rychlá navigace k souborům – vyhledávání podle názvu souboru, třídy, memberu, atp. Moje nejčastější klávesová zkratka byla Shift+Alt+T, hledání souboru.

Visual Studio mělo už v předchozích verzích funkci Navigate to… pod klávesovou zkratkou Ctrl+,. Alternativou bylo i Ctrl+ů – hledání v Solution Exploreru. Ani jedna z těchto variant však kvalitativně ani zdaleka nesahala Resharperu po paty.

Visual Studio 2017 udělalo v tomto značný krok kupředu. Původní Navigate to… se proměnilo v nové Go to… (kromě Ctrl+, přibyla i klávesová zkratka Ctrl+T) a umožňuje už samostatné hledání v souborech/memberech/…

image

Kdo je zvyklý z Resharperu, syntaxe je zde trochu jiná a je to o zvyk. Kromě klávesových zkratek přímo na jednotlivé typy vyhledávání lze použít i Go To All… (Ctrl+T) a přepínač v podobě prvního znaku vyhledávací fráze:

image

Největší slabinou zatím zůstává, že výsledky vyhledávání nejsou seřazeny podle relevance, ale podle abecedy. Občas je to tedy porod:

image

…taková blbost, ale otráví to, když ImportedBook.cs najdete až na třetí stránce a neexistuje syntaxe, jak to dopravit nahoru, dokud existují odpovídající soubory (nebo jsem alespoň zatím nenašel, jak to ochočit). Až na tyto výjimky se s tím však zdá se žít dá, byť plnohodnotná náhrada Resharperu to není.

Kdo by se s tím nesžil, toho odkážu na alternativní doplňky, které jsem zkoušel při své VS2015 #NoResharper challenge:

VS2017 #NoResharper Challenge: Navigace z Controlleru na View

S Resharperem je v Controllerech pohodlná navigace přes Ctrl+Click, aby se člověk dostal na View.

V čistém VS2017 se dá z Controlleru používat:

  • Ctrl+M, Ctrl+G = Go To View
  • Ctrl+M, Ctrl+V = Add View

VS2017 #NoResharper Challenge: Refactorings

Další podstatnou věcí, kterou R# přináší, je mnoho drobných refactoringů. Osobně jsem v tomto příznivcem Roslynu (Compiler Services), takže jsem už při předchozích #NoResharper pokusech nějaké poznatky nabral:

  • Introduce And Initialize Local Field – Úplně na začátku, dokud nic nebylo, napsal jsem jednu vlastní extension.
  • Refactoring Essentials – pro VS2015 jsem používal Refactoring Essentials. Bohužel poslední release je půl roku starý a pro VS2017 zatím verze není.
  • Roslynator Refactorings 2017 – Letmým hledáním pro VS2017 nacházím tento doplněk od Josefa Pihrta, který vypadá celkem obstojně, co se nabízeného rozsahu refactoringů týče. Navíc jde o českou produkci, tak proč to nezkusit a nepodpořit.

Jestli mi budou nějaké refactoringy chybět, pokusím se najít další/jiné náhrady, popř. je zařadím na seznam „Co jsem musel obětovat“ a uvidíme, co na něm nakonec zbude.

VS2017 #NoResharper Challenge: Duplicate Line (Ctrl+D)

Jako téměř s každou novou verzí Visual Studia, nechávám se pravidelně unést představou, že by to šlo bez Resharperu, střelím se do nohy, vypnu Resharper a zkouším to bez něj (s pomocí samotného VS a minimalistickými extensions).

Dnes jsem se tedy opět vydal na tento pokus a budu vás v jednotlivých postech seznamovat s tipy, jak funkce R# nahradit. Jestli to nakonec celé uzavřu zapnutím R#, nebo vydržím bez něj, to jsem sám zvědav (naposledy jsem opustil R# s upgradem z VS2003 na VS2005 a vydržel jsem to bez R# až do VS2012, kdy mi začaly některé funkce výrazně chybět.)

První drobnost, kterou mi R# usnadňoval život, byla klávesová zkratka Ctrl+D na duplikaci řádku. Dá se bez toho určitě žít. Kdo by to potřeboval, je na to minimalistický doplněk:

https://marketplace.visualstudio.com/items?itemName=ctlajoie.DuplicateSelection

[Updated] VS2013, VS2015, VS2017: Když v code-behind nefunguje F7 pro přechod do markupu

VS2015 Update: Úplně stejně se mi chovalo VS2015 pro defaultní „Web Development (Code Only)“ sadu nastavení. Níže uvedený postup pomohl.

Nějakou shodou okolností mi Visual Studio 2013 přestalo reagovat na F7 pro přechod z code-behind text-editoru na ASPX-markup editor.

V nastavení jsem zjistil, že F7 je asociováno na command View.ViewCode (Global). Stačilo přidat pro kontext Text Editor command View.ToggleDesigner.

image

UPDATE: VS2017 úplně stejně.