Skip to content

Exercícios

Nuno Leite edited this page May 25, 2020 · 7 revisions

Exercício 01

Instalar o Visual Studio 2017 em INGLÊS

Exercício 02

Escrever o código C# correspondente ao programa IL ex1.il

Exercício 03

Considere a definição da classe Program em Common Intermediate Language (CIL). Indique e justifique (descrevendo o que faz cada um dos métodos), o output resultante da execução do programa. Para consultar o significado das operações IL siga este link.

Exercício 04

Considere o código fonte em Sum.cs. Compile para .exe.

  • Usando o ildasm, grave o código intermédio de Sum.exe em Sum.il
  • Abra o Sum.il num editor de texto e analise o código intermédio.
  • No método SumTwo presente em Sum.il, duplique a instrução ldarg.0 de maneira a que o argumento no índice 0 seja carregado duas vezes para o stack de avaliação.
  • Comente a linha com o código .maxstack 2
  • Recompile o assemly usando a ferramenta ilasm.exe
    • ilasm Sum.il /EXE /OUTPUT=Sum2.exe
  • Execute a nova aplicação
  • Verifique a nova aplicação com o peverify.exe e analise o resultado

Exercício 05

Escreva a classe Student com os seguintes membros:

  • propriedades get/set (o setter é privado): string Name, int Number
  • Construtores: Student(), Student(int nr, string name)

Realize um programa de teste que cria objetos Student e imprime a sua informação na consola. Realize um programa que faz introspeção (usando o namespace System.Reflection) à classe Student; deve obter o representante do tipo (typeof(Student)) e de seguida apresentar na consola todos os membros públicos (propriedades e construtores) definidos no tipo Student.

Exercício 06

O método GetAssembly(Type t) de Assembly (Assembly.GetAssembly(Type t)) retorna um representante do componente (Assembly) onde foi definido o tipo t. Usando este método e ainda o GetTypes() implemente a função utilitária List<Type> GetDerivedTypesOf(Type t) que retorna uma lista com todos os tipos que estendam direta ou indiretamente de t.

Exercício 07

Considere a classe Student presente em Exercicio7.cs. Implemente a classe ValidatorAttribute (presente em ValidatorAttribute.cs) que corresponde ao atributo aplicado à propriedade Nr. Além de escrever esta classe, complete também a classe NumberValidator de acordo com a sugestão de implementação presente nos comentários da classe.

Exercício 08

  1. class Sammy : Attribute { public int Nr { get; set; } }
  2. [Sammy(Nr = 71)] class Game { }
  3. [Sammy(Nr = App.Foo())] class Deal { }
  4. public class App {
  5.   public static int Foo() { return 17; }
  6.   static void Main() {
  7.     typeof(Game).GetCustomAttribute().Nr = 19;
  8.     Console.WriteLine(typeof(Game).GetCustomAttribute().Nr);
  9.   }
  10. }

Para a definição dada de Sammy, Game, Deal e App:
a) __ a instrução da linha 3 dá erro de compilação.
b) __ a instrução da linha 8 retorna 71.
c) __ a instrução da linha 7 lança uma excepção.
d) __ a instrução (new Sammy()).Nr = 15; dá erro de compilação.

Exercício 09

interface IBean {
  void Set(int v);
  int Get();
}
struct S : IBean {
  public int x;
  public void Set(int v) { this.x = v; }
  public int Get() { return this.x; }
}

Dadas as variáveis s e i definidas pelas expressões: S s = new S(); IBean i = s;
a) __ A execução de ((IBean) s).Set(11); Console.WriteLine(s.x); tem o output 11.
b) __ A execução de ((S) i).Set(11); Console.WriteLine(i.Get()); tem o output 11.
c) __ A execução de s.x = 11; Console.WriteLine(i.Get()); tem o output 11.
d) __ A execução de s.Set(11); Console.WriteLine(i.Get()); tem o output 11.

Exercício 10

Com as classes do espaço de nomes Reflection.Emit...
(a) ____ é possível acrescentar métodos a classes já existentes.
(b) ____ é possível acrescentar novos tipos num assembly existente.
(c) ____ é possível gerar mais do que uma definição de um tipo no presente assembly dinâmico.
(d) ____ é possível usar um tipo gerado num assembly dinâmico mesmo que não se guarde a referência para a instância de Type na altura da geração.

Exercício 11

class​ ​ R ​ { ​ public​ ​ int​ i; }
struct​ ​ V ​ { ​ public​ ​ int​ i; }
... ​ public​ ​ static​ ​ void​ Main() {
  R ​ r = ​new​ ​R();
  R ​ r2 = ​new​ R();
  V ​ v = ​new​ V();
  V ​ v2 =​ new​ ​ V ​ ();
  Console​.WriteLine(v.Equals(v));
  Console​.WriteLine(v.Equals(v2));
  Console​.WriteLine(object.ReferenceEquals(v, v));
  Console​.WriteLine(r.Equals(r));
  Console​.WriteLine(r.Equals(r2));
}

Relativamente ao código acima...
a) ___ ... são realizadas duas operações de​ box ​e o resultado é: true, true​, true, true, false.
b) ___ ... são realizadas cinco operações de​ box resultantes das chamadas a​ WriteLine(object)​.
c) ___ ... são realizadas quatro operações de box e o resultado é: ​true, true​, false,​ true, false.
d) ___ ... é possível eliminar algumas operações de​ box ocorridas em ​Main​ sem alterar o código de​ Main​ e sem alterar a categoria de​ R​ e​ V, mas fazendo outras alterações ao código apresentado.

Exercício 12

class A {
  public virtual void Foo() { }
}
class App {
  void Main() {
    A a = new A();
    a.Foo();
  }
}

Para a instrução a.Foo() o compilador de C# gera: ldloc.0 callvirt instance void A::Foo()
Alterando a definição de Foo para:
a) ___ public void Foo(){} o compilador gera: ldloc.0 call instance void A::Foo()
b) ___ public void Foo(){} o compilador gera: call instance void A::Foo()
c) ___ public static void Foo(){} e a.Foo(); alterada para A.Foo(); o compilador gera: ldloc.0 call void A::Foo()
d) ___ public static void Foo(){} e a.Foo(); alterada para A.Foo(); o compilador gera: call void A::Foo()

Exercício 13

Escreva em IL o código do construtor e do método InvokeAll da classe B.

delegate object Func(int p);
abstract class A {
   protected Func Handlers { get; set; }
   protected int MaxNumHandlers { get; set; }
   protected A(int maxNumHandlers) {
     this.MaxNumHandlers = maxNumHandlers;
   }
} class B : A
{
   public B() : base(10) { Handlers = Bundle; }
   private object Bundle(int p) { return p; }
   public object InvokeAll(object parameter) {
     return Handlers((int)parameter);
   }
}

Exercício 14

Acrescente à interface IEnumerable<T> suporte para a operação lazy genérica Chunk, que recebe uma sequência de T e produz uma nova sequência de sequências de T (i.e. IEnumerable<IEnumerable<T>>) obtida separando a sequência fonte de acordo com o predicado passado a Chunk (e.g. v => v % 2 == 0). Ou seja, o último elemento de cada subsequência satisfaz o predicado, sendo que os anteriores elementos não. As sequências deverão ser lazy.

int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IEnumerable<IEnumerable> chunked = numbers.Chunk(v => v % 2 == 0);
foreach (IEnumerable s in chunked) {
   Console.WriteLine(String.Join(",", s));
}
Output:
1,2
3,4
5,6
7,8
9,10