Konferencja C2C 2009 dobiegła końca, zdobyliśmy trochę wiedzy i poznaliśmy nowych ludzi. Zostały miłe wspomnienia i odliczanie do C2C 2010. Zanim przejdę do rozwiązań konkursu "kartkowego", chciałbym podziękować jeszcze raz wszystkim uczestnikom za przybycie (ze wszystkich zarejestrowanych na ścieżkę .NET nie stawiły się mniej więcej tylko 2 osoby!), sponsorom za wsparcie i pozostałym organizatorom za poświęcenie swojego czasu dla stworzenia tak wspaniałego wydarzenia (szczególnie tym najbardziej zasłużonym – będą wiedzieć którzy to :) ).
Konkurs jak przypomnę składał się z 5 pytań i miał naturę "haczykowatą" oraz miał za zadanie być jak najtrudniejszy. Jak wyszło oraz czy zadania były fajne, okaże się w komentarzach :]
Zadanie 1
class A
{
protected int i = 2;
}
class B : A
{
private int i;
public B() {
i = 2009;
}
}
class C : B
{
public int GetNumber()
{
return i;
}
}
Wywołanie:
C c = new C();
int result = c.GetNumber();
Jaki będzie wynik wykonania programu:
1. Zmienna „result” będzie równa 2,
2. Zmienna „result” będzie równa 2009,
3. Zmienna „result” będzie równa 0,
4. Kod się nie skompiluje,
5. Wystąpi błąd w czasie działania aplikacji.
Prawidłowa odpowiedź to oczywiście 1.
Podczas inicjalizacji konstruktora w klasie B, "i" zmieni się tylko lokalnie, ponieważ jest private. W klasie C, zmienna "i" będzie pobrana z klasy A, gdzie wynosi 2.
Zadanie 2
byte a = 10;
byte b = 01;
byte c = a + b;
Jaki będzie wynik wykonania programu:
1. Zmienna „c” będzie zawierać liczbę 1001,
2. Zmienna „c” będzie zawierać liczbę 11,
3. Zmienna „c” będzie zawierać liczbę 3,
4. Kod się nie skompiluje,
5. Wystąpi błąd w czasie działania aplikacji.
Prawidłowa odpowiedź to 4.
Kod się nie skompiluje, ponieważ domyślnym typem wartości z dodawania jest integer (int), a przypisanie byte c = integer; - bez rzutowania, rozpoznawane jest jako błąd (integer może nie zmieścić się w byte i mogą zostać utracone dane).
Zadanie 3
class A
{
public A(int number)
{
number = number;
}
public int number = 2;
}
class B : A
{
public B(int number)
{
number = new A(number).number;
}
}
class C : B
{
public C(int number)
: base(number)
{
}
}
Wywołanie:
C c = new C(2009);
int result = c.number;
Jaki będzie wynik wykonania programu:
1. Zmienna „result” będzie zawierać liczbę 2,
2. Zmienna „result” będzie zawierać liczbę 2009,
3. Zmienna „result” będzie zawierać liczbę 0,
4. Kod się nie skompiluje,
5. Wystąpi błąd w czasie działania aplikacji.
Prawidłowa odpowiedź to 4.
To zadanie polegało na wykryciu braku konstruktora bezparametrowego w klasie A. Jak zapewne każdy z nas wie, gdy w klasie istnieje jakikolwiek inny konstruktor, to kompilator nie generuje tego domyślnego bez parametru. W tym zadaniu w klasie B, poszukiwany jest domyślny bezparametrowy konstruktor z klasy A, który nie istnieje i kod w związku z tym się nie kompiluje.
Zadanie 4
Dana jest następująca tablica:
string[] imiona = { "Adam", "Ala", "Michał" };
Który fragment kodu poprawnie wyświetli imiona na konsoli?
1. foreach (var imie in imiona.Where(imie => imie.IndexOfAny(new char[] { 'a' }) > 0)) {
Console.WriteLine(imie ?? String.Empty.ToString()); }
2. foreach (int imie in imiona.SingleOrDefault(imiona => imiona.Length)) {Console.WriteLine(imiona[i]);}
3. Array.ForEach((from imie in imiona select imie.ToString()), imie => Console.WriteLine(imie));
4. foreach (string imie in imiona) { Console.WriteLine(imiona[imie.IndexOf(0)]); }
5. foreach (string imie in imiona) { Console.WriteLine(imiona); }
Prawidłowa odpowiedź to 1.
Trochę LINQu pomieszane z czym się dało. Szacunek dla tych którzy potrafili przeanalizować ten kod. :]
Zadanie 5
class Parent
{
static Parent()
{
_message = "Hello!";
}
static public string Message
{
get { return _message; }
}
static protected string _message;
}
class Child : Parent
{
static Child()
{
_message = "Hello, World!";
}
}
Wywołanie:
Console.WriteLine(Child.Message);
new Child();
Console.WriteLine(Child.Message);
Jaki będzie wynik wykonania programu:
1. Na konsole zostaną wypisane znaki: "Hello!", "Hello!",
2. Na konsole zostaną wypisane znaki: "Hello!", "Hello, World!",
3. Na konsole zostaną wypisane znaki: "Hello, World!", "Hello, World!",
4. Na konsole zostaną wypisane znaki: "Hello, World!", "Hello!",
5. Kod się nie skompiluje.
Prawidłowa odpowiedź to 2.
Ostatnie zadanie i chyba najtrudniejsze ze wszystkich, wymagało bardzo dobrej znajomości kompilatora C#. Niektórzy nazywają to zachowanie Bugiem kompilatora. Wartość _message nie zostanie ustawiona dopóki nie było pierwszego odwołania do konstruktora Child. Pierwsze odwołanie new Child() ustawia nową wartość zmiennej _message. Stąd też najpierw tekst "Hello!" a później "Hello, World!".
Podsumowanie
Dziękuje wszystkim którzy wzięli udział w konkursie, mam nadzieje że podobał się Wam i gratuluje wygranych!
Pozdrawia,
Jacek Ciereszko