Řešení vzorové zkouškové písemky 2014

Cílem semináře je seznámit posluchače s jazykem C#, prostředím platformy .NET a tvorbou aplikací s grafickým uživatelským rozhraním. Předpokládají se znalosti objektově orientovaného programování.
Oracions
Matfyz(ák|ačka) level I
Příspěvky: 12
Registrován: 30. 1. 2014 16:18
Typ studia: Informatika Mgr.

Řešení vzorové zkouškové písemky 2014

Příspěvek od Oracions »

Vzorová písemka 2014

Předpokládejme dynamickou knihovnu Lib.dll, která
byla přeložena s následujícím kódem (říkejme této
variantě verze 1):

Kód: Vybrat vše

public class A { 
 public void m(int a = 10, int b = 10) { 
 Console.Write("X {0} {1}", a, b); 
 } 
 public void g() { 
 Console.Write("A1"); 
} } 
public class B : A { 
} 

Dále předpokládejme spustitelnou assembly App.exe,
která byla přeložena vůči assembly Lib.dll uvedené
výše. Kód assembly App.exe je následující:

Kód: Vybrat vše

class Program { static void Main() { 
 A a = new B(); 
 a.m(42); 
 a.g(); 
} } 

Nyní předpokládejme, že vznikla nová verze assembly
Lib.dll (říkejme jí verze 2) s tímto kódem:

Kód: Vybrat vše

 
public class A { 
 public void m(int a = 0, int b = 0) { 
 Console.Write("Y {0} {1}", a, b); 
 } 
 public void m(int a) { 
 Console.Write("Z {0}", a); 
 } 
 public void g() { 
 Console.Write("A2"); 
} } 
public class B : A { 
 public void g() { 
 Console.Write("B2"); 
} } 

Zajímá nás, jak se bude chovat aplikace App.exe,
přeložená vůči verzi 1 assembly Lib.dll, pokud ji
spustíme a dispozici bude pouze Lib.dll verze 2.

1. Nejprve rozhodněte, co vypíše volání metody m:
V CIL kódu bude napsáno "zavolej metodu A.m(int,int) s argumenty 42,10, protože vhodná signatura volané metody se vybírá za překladu, a volitelné parametry se dosazují také během překladu. Vypíše se tedy Y 42 10

2. Dále rozhodněte, co vypíše volání metody g:
V CIL kódu je "A.g()", metoda g v nové verzi knihovny není virtuální, vypíše se tedy "A2".

3. Pro následující program rozhodněte, co vypíše na
standardní výstup:

Kód: Vybrat vše

class Program { 
 static void Main() { 
 Func<int, Func<int, int>> f = 
 x => (( 
 (Func<int, int>) (y => x++ + y++) 
 ) + ( 
 y => x++ + y++ 
 )); 
 Console.WriteLine(f(10)(20)); 
 } 
} 
Vypíše 31. f je instance delegáta Func<int, Func<int, int>>, která bere jako argument int a vrací delegáta, který bere int a vrací int. Volání f(10) tedy vrátí instanci Func<int,int>, která se zavolá s argumentem 20 a její výsledek se vypíše. f má dvě vnitřní anonymní funkce, obě využívají x, což je parametr. x je tedy zachycen a extrahován do anonynmní třídy. Generovaný kód, kdybychom ho dekompilovali zpět do CSharpu, bude vypadat asi takhle:

Kód: Vybrat vše

class __a {
 int x;
 public __firstFunction(int y)
 {
  return (x++) + (y++); // Inkrementace má vyšší prioritu než sčítání.
 }
 public __secondFunction(int y)
 {
  return (x++) + (y++);
 }
 public __a(int x)
 {
  this.x = x;
 }
}
class Program {
 static Func<int, int> __mainFunction(int x)
 {
   __a a = new __a(x);
   Func<int,int> f;
   f += a.__FirstFunction;
   f += a.__secondFunction;
   return f;
 }
 static void Main() {
  Func<int, Func<int,int>> f = Program.__mainFunction;
  Console.WriteLine(f(10)(20));
 }
}
Nejprve se spustí poté první funkce, pak druhá. První funkce vrátí 30 a inkrementuje x. Druhá funkce vrátí 31 a inkrementuje x. Pokud jsou v jedné instanci delegáta pointery na dvě funkce, vrací se jen výsledek té poslední z nich, výsledek tedy bude 31.

4. Předpokládejme následující strukturu, která se bez chyb přeloží:

Kód: Vybrat vše

struct X<T> { 
 private T t; 
 
 public static implicit operator T(X<T> x) { 
 return x.t; 
 } 
 
 public static implicit operator X<T>(T t) { 
 X<T> x; 
 x.t = t; 
 return x; 
 } 
} 

Dále předpokládejme proměnné typu A[] a typu X<A>[].
Pro některé typy A se tyto proměnné budou v některé
situaci chovat zcela rozdílně. Rozhodněte, pro které:


NE: System.Double
NE: System.Decimal
ZÁLEŽÍ NA INTERPRETACI: libovolnou statickou třídu (static class)
NE: libovolný uživatelem definovaný výčtový typ (enum)
ANO: System.IO.FileStream (hint: není sealed)
ANO: System.Object

System.Object a System.IO.FileStream jsou referenční typy a tedy pro ně funguje kovariance polí. Struktury jako X<A> jsou hodnotové typy a nefunguje pro ně kovariance polí. Mohu tedy udělat object[] o = new System.IO.FileStream[]; ale už nemohu object[] o = new double[];. Je možné, že i pro hodnotové typy se chovají tyhle věci nějak rozdílně, ale to už Ježek slyšet nechce (dokázat, že se chovají stejně, by šlo jen dost těžko). Pro static class obě použití hodí kompilátorovou chybu, ale každé jinou "You cannot create an array of static classes" versus "You cannot use a static class as a type parameter."

5. Předpokládejme následující program:

Kód: Vybrat vše

abstract class A { 
 public virtual void f() { 
 Console.WriteLine("A.f"); 
 }  
 public abstract void g(); 
}  
class B : A { 
 public override void f() { 
 Console.WriteLine("B.f"); 
 }  
 public override void g() { 
 base.f(); 
} }  
class Program { 
 static void Main() { 
 A a = new B(); 
 a.g(); 
} } 

Rozhodněte, co vypíše na standardní výstup:
Do CIL kódu se volání přeloží jako "callvirt A::g()". Funkce g je virtuální, protože je abstraktní, tedy se zavolá funkce B::g, která volá base.f(). Klíčové slovo base je jedním ze dvou způsobů, jak zavolat funkce nonvirtuálně v CSharpu. Druhý způsob je volání konstuktoru předka. base.f() se tedy přeloží jako "call A::f" a zavolá se A.f nevirtuálně, tedy se vypíše A.f.

6. Pro typ int určete velikost lokálních proměnných tohoto typu:
4 bajty (vynuceno specifikací, stejně jako v Javě)

7. Označte všechny jazykové konstrukty, jejichž implementaci ve třídě může vynutit interface I1, který tato třída implementuje:
NE (narozdíl od Javy): datovou položku (field)
NE (je statická): extension metodu
ANO: vlastnost (property)
ANO: implementaci metod jiného interfacu I2
NE (nelze používat žádné modifikátory): abstraktní metodu
NE (nic takového v CSharpu neexistuje): kopírovací konstruktor (copy constructor)
NE: operátor ==
ANO: indexer („operátor []“)

Interfacy mohou dědit od libovolného počtu rozhraní a mohou obsahovat jako položky právě:
Veřejné metody bez modifikátorů, jsou implicitně public, pouze signatury, žádně tělo.
Eventy.
Properties (lze vynutit public get nebo public set)
Indexery.

8. Předpokládejme následující program, který se bez chyb přeloží:

Kód: Vybrat vše

class A<T> { 
 public class B : A<int> { 
 public void f() { 
 Console.WriteLine( 
 typeof(T).ToString()); 
 } 
 public class C : A<int>.B { } 
} } 
class Program { static void Main() { 
 var c = new A<string>.B.C(); 
 c.f(); 
} } 
Fajn. Takže c je instance typu A<string>::B::C. Uvnitř ní platí, že T je alias System.String.
Do jakého CIL kódu se přeloží c.f()? Určitě to bude "callvirt NĚCO", ale co? Třída A<string>::B::C metodu f neobsahuje, nemá ani žádnou extension metodu, tak se podíváme do jejího předka. Tím je A<int>::B. Ta ovšem už metodu B obsahuje, kód c.f() se tedy přeloží do CIL jako "callvirt A<int>::B::f()". Uvnitř této funkce je tedy T alias za System.Int32. Vypíše se System.Int32.
Složitější verzi této otázky najdete na http://stackoverflow.com/questions/2117 ... sted-types

9. Předpokládejme následující program:

Kód: Vybrat vše

class Profile { 
 public static Profile CreateProfile( 
 string name) { 
 Profile p = new Profile(); 
 StreamReader r = null; 
 try { 
 r = new StreamReader( 
 name + ".profile"); 
 ... 
 } catch (IOException ex) { 
 Debug.Write("..."); 
 
 } 
 ... 
 return p; 
} } 
Vyberte nejvhodnější způsob, jak dokončit ošetření výjimky na označeném místě:
NE (ztratí informace o zdroji výjimky): throw new ArgumentException("...");
ANO (vyhodí správný typ výjimky, pokud v dokumentaci říkáme, že name musí splňovat nějaké požadavky): throw new ArgumentException("...", ex);
NE (ztratí informace o zdroji výjimky): throw new IOException();
NE (ztratí informace o zdroji výjimky): throw new IOException("...");
ANO (vyhodí správný typ výjimky, záleží na situaci): throw new IOException("...", ex);
NE (ztratí informace o call stacku): throw ex;
ANO (zachová call stack): throw;

Tohle nám přišlo jako kontroverzní otázka.
Odpovědět

Zpět na „NPRG035 Jazyk C# a platforma .NET“