Pokazywanie postów oznaczonych etykietą visual studio. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą visual studio. Pokaż wszystkie posty

piątek, 3 kwietnia 2015

[C#|Visual Studio] C# 6.0 - co nowego ?

Microsoft regularnie co 2 - 3 lata wypuszcza nam nową wersję C#. Dotychczas wyglądało to tak:
2002: C# 1.0
2005: C# 2.0 (generyki)
2007: C# 3.0 (LINQ)
2010: C# 4.0 (dynamic)
2012: C# 5.0 -  (async)

Mamy 2015 rok i wiemy już mniej więcej, czego możemy się spodziewać po nowej wersji C#. Poniżej wybrane nowe funkcjonalności, które będą dostępne w Visual Studio 2015:

Auto-Property Initalizers


public class User
{
    public Guid Id { get; } = Guid.NewGuid();
}


Już wcześniej pozbawiono nas konieczności definiowania backing fields, teraz dodano możliwość automatycznego inicjalizowania danych.

Dictionary Initializers

Dictionary<string, User> _defaultUsers = new Dictionary<string, User>(){

    {"admin", new User("admin")},
    {"guest", new User("guest")}

}


Nowy, inny sposób:


Dictionary<string, User> _defaultUsers = new Dictionary<string, User>(){

    ["admin"] = new User("admin")},
    ["guest"] = new User("guest")}

}

Pierwszy sposób (stary) to seria wywołań metody Add, drugi to seria odwołań przez indekser.

Kolejna zmiana jest taka, że paramsy (słowo kluczowe params) mogą być jako IEnumerable<T>, nie muszą być tablicą T.

public int Sum(params IEnumerable<int> numbers){
    return numbers.Sum(n => n);
}

Mamy nowe literale: bitowy (0b1100) oraz poprawiający czytelność (1_000_000_000).

Wywoływanie statycznych metod:

W C# 6 można wywoływać statyczne metody bez podawania nazwy klasy, jeżeli typ jest statyczny i załączymy odpowiedni using.


using System.Console;

public static void Main(){
    Write("Writted without type specification");
}


W przypadku konfliktów zawsze wygra metoda statyczna (podobna interpretacja jak w przypadku extension methods).

Conditional access operator:


var name = action.?Method.?Name ?? "no name";


Sprawdzimy, czy wartości są różne od null i jeśli któraś jest nullem, to wartość po lewej stronie zostanie ustawiona na null. Dodatkowo null - coalesce operator ustawi nam domyślną wartość.

Ponadto wewnątrz bloków catch można będzie wołać instrukcje poprzedzone keywordem await.

Exception filters:


catch(Exception ex) if(ex.InnerException == null){

}


Jeśli wyrażenie zwróci false, to wyjątek nie zostanie złapany.

Operator nameof:

zamiast:

throw new ArgumentNullException("name")

będzie można napisać


throw new ArgumentNullException(nameof(name))

środa, 24 lipca 2013

[Visual Studio] Unit Testy

Pisząc Unit Testy należy pamiętać o zasadzie 3xA: Arrange Act Assert. Oznacza ona, że metody testujące powinny składać się z pewnego szablonu: na początku przypisujemy zmienne i oczekiwane wyjście, później wykonujemy test, a na końcu sprawdzamy, czy wynik jest poprawny. Wygodnym Frameworkiem do pisania Unit Testów w VS jest NUnitFramework. Instalujemy go za pomocą NuGeta.


Przykładowa metoda do przetestowania:

public class StringHelper
{
    public static int CountLetters(string word, char letter)
    {
        return word.Count(c => c == letter);
    }
}

...i odpowiadający mu UnitTest.

[TestFixture]
public class StringHelperTest
{
    [Test]
    public void CountLettersTest()
    {
        //Arrange
        var @string = "copacabana";
        var letter = 'a';
        int expected = 4;

        //Act
        int current = StringHelper.CountLetters(@string, letter);

        //Assert
        Assert.AreEqual(expected, current);
    }
}

Dla klas i metod obowiązuje pewna konwencja dodawania na końcu nazw słowa Test. Unit Testy można także bez problemu Debugować. Korzystając z dodatku Resharper można uruchamiać pojedyncze testy bezpośrednio w kodzie.


Przydatnymi atrybutami są SetUp i TearDown. Będą to metody wykonywane raz odpowiednio przed i po sesji testów.


[SetUp]
public void Init()
{
    Console.WriteLine("Initializing...");
}

[TearDown]
public void Clean()
{
    Console.WriteLine("Shutting down..."); 
}

Testy można także w razie potrzeby grupować w kategorie, również przez odpowiedni atrybut.

[Test]
[Category("another tests")]
public void CountLettersTest2()
{
    //Arrange
    var @string = "copACABana";
    var letter = 'a';
    int expected = 2;

    //Act
    int current = StringHelper.CountLetters(@string, letter);

    //Assert
    Assert.AreEqual(expected, current);
}

Dzięki temu z poziomu GUI możemy odpalać na przykład tylko testy z danej kategorii.


Ostatnia ciekawa funkcjonalność to timeouty. Możemy ustawić dla danej metody maksymalny czas wykonania poprzez atrybut MaxTime, np. [MaxTime(5000)].

sobota, 2 lutego 2013

[C#|Visual Studio] Threading: Podstawy

W języku C#, niezależnie od tego, czy tworzymy aplikację konsolową, WinFormsową czy WPFową, domyślnie operacje zawsze będą się wykonywały w jednym wątku, tworzonym przez CLR. Wątkami w .NEcie zarządza specjalny mechanizm zwany thread scheduler. Na jednordzeniowej maszynie wielowątkowość realizowana jest poprzez podział czasu pracy procesora, natomiast na wielordzeniowej wątki uruchamiane są na wszystkich rdzeniach, jednak należy pamiętać, że system operacyjny czy też inne uruchomione programy również korzystają z CPU, tak więc podział czasu i przełączanie wątków w praktyce odbywa się zawsze. Czas przełączenia szacuje się na dziesiątku milisekund.

Najprostszym sposobem na zrównoleglenie wykonywanych operacji jest klasa Thread. Poniższy przykład pokazuje, jak przy jej użyciu na wieloprocesorowej maszynie wykonywać operacje naprzemiennie.

public static void Run()
{
    Thread t = new Thread(WriteY);          
    t.Start();
    for (int i = 0; i < 100; i++)
    {
        Thread.Sleep(i);
        Console.Write("x");
    } 
        
}

static void WriteY()
{
    for (int i = 0; i < 100; i++)
    {
        Thread.Sleep(i);
        Console.Write("y");
    }
}

Warto pamiętać, że dla każdego wątku tworzony jest osobny memory stack. Informacje pomiędzy wątkami mogą być przekazywane np. poprzez zmienne statyczne. Nieumiejętne ich wykorzystanie może jednak spowodować poważne problemy. Aby uniknąć np. sytuacji, w której dwa wątki zapisują w tym samym czasie dane do jednej zmiennej, należy użyć tzw. Exclusive Lock. Użycie słowa kluczowego lock powoduje, że tylko jeden wątek w danej chwili może korzystać z zasobu, drugi musi poczekać.

public class LockTest
{
    static bool done;
    static readonly object locker = new object();

    public static void Run()
    {
        new Thread(Go).Start();
        Go();
    }

    static void Go()
    {
        lock (locker)
        {
            if (!done) { Console.WriteLine("Done"); done = true; }
        }
    }
}

Blokowany wątek nie zużywa zasobów CPU.

Kolejną ważną operacją jest Join, służący do synchronizowania kolejności wykonywania operacji. Jeżeli z poziomu jednego wątku startujemy inny podrzędny, możemy zażądać aby dalsze wykonywanie kodu wstrzymać do zakończenia działania tego podrzędnego wątku.

public class JoinTest
{
    public static void Run()
    {
        Thread t = new Thread(Go);
        t.Start();
        for (int i = 0; i < 100; i++) Console.Write("x");
        t.Join();
        Console.WriteLine("Thread t has ended!");
    }

    static void Go()
    {
        for (int i = 0; i < 1000; i++) Console.Write("y");
    }
}

Wątki można nazywać, co przydaje się podczas debugowania w Visual Studio. Można im także nadawać priorytety. Nadanie priorytetu decyduje o tym, ile czasu procesor poświęci na dany wątek. Domyślny priorytet to Medium.

public class ThreadNamePriorityTest
{
    public static void Run()
    {
        Thread.CurrentThread.Name = "Main Thread";
        Thread worker = new Thread(Go);
        worker.Name = "Worker";
        worker.Priority = ThreadPriority.BelowNormal;
        worker.Start();
        Go();
    }

    static void Go()
    {
        Console.WriteLine("Hello from " + Thread.CurrentThread.Name);
    }
}

czwartek, 15 listopada 2012

.NET Framework

Wszystko na temat Visual Studio, języka C# i technologii opartych na platformie .NET Framework:

niedziela, 4 listopada 2012

[C#|Visual Studio] DebuggerBrowsableAttribute

Kolejnym atrubutem pomocnym podczas debugowania programu jest DebuggerBrowsable znajdujący się, podobnie jak DebuggerDisplay w System.Diagnostics. Atrybut ten okazuje się pomocny, gdy przeglądamy obiekty składające się z dużej ilości properties, a chcemy śledzić stan jedynie niektórych z nich, bądź wyświetlać je w sposób łatwiejszy do podglądu. Nad każdym property można umieścić atrybut DebuggerBrowsable, który w konstruktorze przyjmuje jedną z trzech opcji.
  • Never - pole lub property nie będzie widoczne po rozwinięciu obiektu w zakładce Locals
  • Collapsed - zachowanie domyślne, obiekt widoczny, ale nie rozwinięty
  • RootHidden - w przypadku wyświetlania kolekcji, jej elementy są widoczne poziom wyżej, bez wyświetlania jej roota. Np. jeśli mamy listę napisów jako property pewnej klasy, to przy ustawieniu RootHidden, wszystkie napisy będą widoczne jako properties tej klasy.
Zasadę działania ilustruje także poniższy przykład.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using D = System.Diagnostics;

namespace DebuggerBrowsableAttribute
{
    public class SampleClass
    {
        [D.DebuggerBrowsable(D.DebuggerBrowsableState.RootHidden)]
        public List<int> RootHidden { get; set; }

        [D.DebuggerBrowsable(D.DebuggerBrowsableState.Collapsed)]
        public int Collapsed { get; set; }

        [D.DebuggerBrowsable(D.DebuggerBrowsableState.Never)]
        public int Never { get; set; }

        public SampleClass()
        {
            Random r = new Random();
            RootHidden = new List<int>();
            RootHidden.Add(r.Next(100));
            RootHidden.Add(r.Next(100));
            RootHidden.Add(r.Next(100));
            Collapsed = r.Next(100);
            Never = r.Next(100);
        }
    }
}


sobota, 3 listopada 2012

[C#|Visual Studio] DebuggerDisplayAttribute

DebuggerDisplayAttribute można znaleźć w System.Diagnostics. Atrybut ten służy do kontroli sposobu, w jaki wyświetlamy daną zmienną w oknie zmiennych debuggera. Przydaje się to np. do klas zawierających kilka properties, które chcemy podejrzeć. Jako argument konstruktora podajemy string z możliwością używania wyrażeń umieszczonych w nawiasach klamrowych {}. W wyrażeniach tych można na przykład podawać nazwy properties, przeprowadzać na nich operacje, czy wywoływać funkcje. Należy jednak pamiętać, że operacja wykona się przy każdym odświeżeniu debuggera, przez co często zmusimy komputer do sporej ilości niekoniecznie potrzebnych obliczeń.

using System;
using D = System.Diagnostics;

namespace DebuggerDisplayAttribute
{
    [D.DebuggerDisplay("Sample class: First: {First}, Second: {Second}, Sum: {Sum()}")]
    public class SampleClass
    {
        public int First { get; set; }
        public int Second { get; set; }

        public SampleClass()
        {
            Random r = new Random();
            First = r.Next(100);
            Second = r.Next(100);
        }

        public int Sum()
        {
            return First + Second;
        }
    }
}

Podczas zatrzymania pracy programu w trybie debug, z automatu otrzymamy: