poniedziałek, 18 stycznia 2010

C# Wishlist

Widać jak szalony naukowiec Hejlsberg tworzy wieloparadygmatowe dzieło :) Z zwyczajnego programowania obiektowego zostało stworzone monstrum :))
Skoro każdy ma swoje życzenie do języka programowania, to ja też mam swoją wish-liste do C#5.0.

Zgodnie z PDC09 meta-programming - compiler as a service, XML Literals (od VB) i Extension propertis and constructor (podobno wiedzą jak to zrobić, ale nie wiedzą jak to dobrze zrobić) oraz Immutable objects

Moja listę featuresów to:
1) Typ atom
Ma taką wartość jaką ma nazwę.

2) Opcjonalność pogrupowania metod, które są ExtensionMethods
NP:
string str = "Jakiś Super Głupi Tekst";
var result = str.Where(x => Char.IsUpper(x)).ToList();
var result2= str.EM.Where(x => Char.IsUpper(x)).ToList(); // W obszarze EM są zawarte wszystkie ExtensionMethods

Obiekt EM to MethodGrouper z listą metod, które wcześniej zdefiniowaliśmy.

Kiedy napiszesz swoje metody dla string i jeszcze korzystasz z metod innej biblioteczki to nagle w intellisense nagle mamy kolekcje 200 metod. Grupowanie nie musi być na poziomie codu, ale VS lub R# mogłoby udostępnić tą opcje na poziomie edytora.

3) Static ExtensionMethods
ExtensionMethods mają wiele zalet:
-przejście ze metody statycznej do metody obiektu
-nie czytamy kodu od środka
-operujemy na typie, a nie na modelu
-działa na obiektach dziedziczonych
Ale miło by było mieć rozszerzenie metod statycznych
NP:
DateTime dt;
DateTime.TryParse(new List{"14","03","2010"},out dt);
czy
int.IsEvenNumber(2);


4) Static Interface
Za każdym razem kiedy piszę klasę generyczną dla struktur takich jak int czy float, chciałbym wywołać metodę Equals, TryParse czy pobrać wartość MaxValue;

5) Interface Agregator
Pewne różne obiekty, które nie są dziedziczone, maja metodę o takiej samej nazwie, parametrach i zwracanym typie.
Więc dlaczego te klasy nie dziedziczą po interfejsie? Z pomocą przyszedł by interfejs agregator który potrafi zgrupować klasy, które maja wspólne metody.

6) Konwersja dla operacji
Mają obiekt char currentChar chciałbym uzyskać następny znak. Aby są prostą operację wykonać należy napisać
(char)((int)currentChar + 1)

Ohyda. Zdecydowanie ładniej kod wygląda w taki sposób:
currentChar + 1

lub
currentChar.Oper(x=>x+1)

gdzie Oper jest metodą dla każdego obiektu.

7)Dokumentacja i tworzenie Tupli
Tuple jak i Typy Anonimowe maja swoje wady i zalety.
Tworząc obiekt
Tuple <int, float, string,List < int> > ifsl = new Tuple < int, float, string,List < int> >(1, 0.3F, "a",new List < int>{11,22}) ;

nie wiemy co oznaczy właściwość Item2 czy Item4. Nie mówię, że chce zmieniać nazwę właściwości, ale komentarz by się przydał z informacją co miał na myśli autor kodu.

Zamiast tworzenie takiego ciągu kodu dla
Tuple < int, float, string,List < int >> ifsl = new Tuple < int, float, string,List < int>>(1, 0.3F, "a",new List < int>{11,22});
var ifsl = new Tuple < int, float, string,List < int>>(1, 0.3F, "a",new List < int>{11,22});
var ifsl = new (1, 0.3F, "a",new List < int>{11,22}); //zapis skrócony


Uważam, iż struktura Tupli będzie coraz bardziej popularna i należy wykorzystać zapis skrócony.

8) Multiple Return Values
Już były próby wykonania metody która mogła by zwrócić kilka wartości z zastosowaniem dynamic i typu anonimowego.

public static dynamic GetPerson(Person p)
{
return new { lName = p.LastName, fName = p.FisrtName, age = p.Age }
}
dynamic d = GetPerson(p);
string lName = d.lName;
string fName = d.fName;
int age = d.age;


Ale poprzez dynamic traci się statyczną typizację, wymaga znajomości właściwości typu anonimowego oraz zapis jest w kilku linijkach.

A jak by wyglądało z zastosowaniem Multi Return Values
NP:
public static (string,string,int) GetPerson(Perons p)
{
return (p.LastName,p.FirstName, p.Age);
}

var lName=GetPerson(p);
var (lName,fName)=GetPerson(p);
var (lName,fName,age)=GetPerson(p);


lub
var [lName,fName,age]=GetPerson(p); //jak w Matlabie


Innym rozwiązaniem jest zastosowanie parametrów out z domyślnymi wartościami, ale dostajemy komunikat "A ref or out parameter cannot have a default value".
O co chodzi. W metodzie z parametrami out można zwrócić więcej wartości.
vodi GetPerson(Person p, out string oLastName, out string oFirstName, out int oAge);
{
oLastName=p.LastName;
oFirstName=p.FirstName;
oAge=p.Age;
}

string lastName;
string firstName;
int age;
GetPerson(p,out lastName, out firstName,out age);


A gdybyśmy zastosowali wartości domyślne. Kod byłby bardziej czytelny.
NP:

void GetPerson(Person p, out string oLastName=p.LastName, out string oFirstName=p.FirstName, out int oAge=p.Age){};


string lastName;
string firstName;
int age;
GetPerson(p);
GetPerson(p, out lastName,out firstname, out age);
GetPerson(p, out lastName);
GetPerson(p, out age);


Gdyby nie wishlisty programistów nie było by postępu języków programowania:)

Więcej info o c#5.0 można poczytać pod tym linkiem oraz inne wishlisty z codebetter i kodefu.