-
Notifications
You must be signed in to change notification settings - Fork 0
Sumários
Aulas:
- 18-02-2019 - Aula 01 - Apresentação
- 21-02-2019 - Aula 02 - Unmanaged, ligação estática
- 21-02-2019 - Aula 03 - Managed, ligação dinâmica
- 25-02-2019 - Aula 04 - Tipos em runtime (Cap 4.1)
- 28-02-2019 - Aula 05 - Programming with Metadata (Cap 4.2)
- 28-02-2019 - Aula 06 - Propriedades (Cap 4.3 Special Methods)
- 07-03-2019 - Aula 07 - Metadata and Extensibility (Cap 4.4)
- 07-03-2019 - Aula 08 - Metadata and Extensibility (Cap 4.4)
- 11-03-2019 - Aula 10 - Reflexão Arrays
- 14-03-2019 - Aula 11 - Laboratório - dúvidas do Trabalho 1
- 14-03-2019 - Aula 12 - Laboratório - dúvidas do Trabalho 1
- 18-03-2019 - Aula 13 - Tipos Valor vs Referência
- 21-03-2019 - Aula 14 - Laboratório - dúvidas do Trabalho 1
- 21-03-2019 - Aula 15 - Laboratório - dúvidas do Trabalho 1
- 26-03-2019 - Aula 16 - Exercícios de Reflexão e Custom Attributes
- 28-03-2019 - Aula 17 - Tipos em runtime e Boxing (Cap 4.1, 5.1 a 5.5)
- 28-03-2019 - Aula 18 - Chamada a Métodos (Cap 6.1 e 6.2)
- 01-04-2019 - Aula 19 - System.Reflection.Emit
- 04-04-2019 - Aula 20 - Laboratório - dúvidas do Trabalho 2
- 04-04-2019 - Aula 21 - Laboratório - dúvidas do Trabalho 2
-
08-04-2019 - Aula 22 -
new
vsoverride
(6.2) - 11-04-2019 - Aula 23 - Laboratório - dúvidas do Trabalho 2
- 11-04-2019 - Aula 24 - Laboratório - dúvidas do Trabalho 2
- 15-04-2019 - Aula 25 - Laboratório - dúvidas do Trabalho 2
- 18-04-2019 - Interrupção lectiva (Páscoa)
- 22-04-2019 - Interrupção lectiva (Páscoa)
- 29-04-2019 - Aula 26 - Sequences
- 02-05-2019 - Aula 27 - Sequences -- expressões lambda e delegates
- 02-05-2019 - Aula 28 - Sequences -- Lazy
- 06-05-2019 - Aula 29 - Sequences -- Generics
- 09-05-2019 - Aula 30 - yield and generators
- 09-05-2019 - Aula 31 - Extension Methods and Linq
- 13-05-2019 - Aula 32 - Delegates (Cap 6.5 do Essential .Net)
- 16-05-2019 - Aula 33 - Laboratório - dúvidas do Trabalho 3
- 16-05-2019 - Aula 34 - Laboratório - dúvidas do Trabalho 3
- 20-05-2019 - Aula 35 - Exercícios: reflexão, interfaces e delegates
- 23-05-2019 - Aula 36 - Laboratório - dúvidas do Trabalho 3
- 23-05-2019 - Aula 37 - Laboratório - dúvidas do Trabalho 3
- 27-05-2019 - Aula 38 - GC (Cap 21 do livro CLR via C# 4th edition)
- 30-05-2019 - Aula 39 - Laboratório - dúvidas do Trabalho 3
- 30-05-2019 - Aula 10 - Laboratório - dúvidas do Trabalho 3
- 03-06-2019 - Aula 41 - Finalize (Cap 21 do livro CLR via C# 4th edition)
- 06-06-2019 - Aula 42 - Exercícios: Sistema de Tipos, Genéricos, Delegates Internals e IL
-
06-06-2019 - Aula 43 - Exercícios: IL,
yield
e sequências lazy
Livro de Referência: Essential .NET, Volume 1: The Common Language Runtime,
18-02-2019
- Regras de Avaliação
- Bibliografia recomendada
- Ferramentas:
csc
,ildasm
,ilasm
,peverify
- Página no Github
- Introdução ao âmbito da disciplina de Ambientes Virtuais de Execução--AVE
- AVE ~ VM (virtual machine)
- Foco no AVE e não na linguagem C#
- Evolução histórica das plataformas .Net e Java
- Exemplos de linguagens para a JVM (Java, kotlin, Scala) e linguagens para .NET (C#, F#, VB)
- Essencial do C# semelhante à linguagem Java. E.g.
class A { static void foo() { }}
- Utilização do compilador de C# de linha de comando (
csc
) - 2 tipos de módulos em .NET:
.exe
(por omissão) e.dll
(csc /t:library
) - Configuração do ambiente consola
VsDevCmd.bat
21-02-2019
- Distinção entre especificação de um AVE (e.g. JVM, CLI) e sua implementação (e.g. Java SE HotSpot, .Net Framework, .Net Core)
- Vantagens do Desenvolvimento de Sw por Componentes:
- Redução da complexidade;
- Promover a reutilização.
- Noção de Componente como uma Peça de Software Reutilizável
- Distinção entre os papéis do programador que fornece um componente e o programador que reutiliza esse componente para a produção de uma aplicação, ou outro componente.
- Unidade de distribuição de componentes em Java: .class e Jar (conjunto de .class).
- Ambiente Unmanaged
<versus>
Managed
- Cenário unmanaged e componentes com código em linguagem máquina (ficheiros .obj);
- Dificuldades da reutilização de componentes em ambiente unmanaged:
- componentes em duas partes: header + obj
- necessitam de um ficheiro de header que descreve os tipos definidos no componente
- necessidade de build para diferentes arquitecturas
- mudanças estruturais (modificação do ficheiro de header) obrigam à recompilação e ligação das aplicações cliente.
- mudanças de comportamento dos métodos obrigam apenas à ligação das aplicações cliente.
- Demonstração de um componente que define um tipo
Ponto
e uma aplicaçãoPontoApp
que reutiliza o componente anterior. - Ferramentas de compilação e ligação em C:
-
cl /c /Zi
-- compila, sem ligar e gera um obj; link /DEBUG comp1.obj comp2.lib etc
-
devenv PontoApp.exe
-- abre o Visual Studio e permite fazer debug.
-
21-02-2019
- Distinção entre Ligação Estática vs Ligação Dinâmica e Tempo de Compilação vs Tempo de Execução
- Cenário managed e componentes com código em linguagem intermédia, e.g.
bytecodes (Java) ou IL (.net).:
- Componentes auto-suficentes: IL + metadata (faz o papel do .h)
- Papel da Metadata na compilação e em tempo de execução---no Verifier do AVE--- garante "safety";
- Jitter (just-in-time compiler) -- responsável pela tradução do código intermédio (IL ou bytecodes) para linguagem máquina.
- Verifier -- responsável por garantir a propriedade de safety, e.g. não existem acessos inválidos a memória.
- Ferramenta
peverify
- Utilização da ferramenta
javap
(java) eildasm
(.net)
- Detalhe da Linguagem IL;
- Modelo de execução em Stack managed;
- Tabela de argumentos e variáveis locais.
- Operadores
st...
eld...
; -
call
,callvirt
enewobj
25-02-2019
- Resolução do TPC
- Categorias de Tipos: tipos valor e tipos referência;
- Valores vs Objectos;
- Tipo
Type
como representante de um tipo -- TipoClass
representante de um tipo em Java. - método
GetType()
deObject
. - O resultado do
GetType()
para o mesmo tipo, retorna sempre a referência para o mesmo representante desse tipo -- a mesma instância deType
. - A VM mantém apenas um representante (instância de
Type
) para cada tipo carregado. - Consulta da propriedade
BaseType
- Tipos valor estendem de
System.ValueType
- Tipos valor não podem ser derivados.
- Teste de igualdade de tipos com base em
GetType
. -
GetType()
e comparação de identidade comtypeof
-
GetType()
vstypeof
- Propriedade
.class
do Java -- operadortypeof(…)
do C#
- Resolução do TPC02
- Método
GetInterfaces()
deType
. -
Reflexão --
System.Reflection
(.Net)<=>
java.lang.reflect
(Java) - Reflexão -- API object oriented sobre a metadata
- Reflexão -- segue as regras que caracterizam um sistema de tipos (CTS em .net)
- API de Reflexão do .net (
System.Reflection
Namespace):Type
,FieldInfo
,MethodInfo
,ConstructorInfo
,PropertyInfo
,EventInfo
e classe abstractaMemberInfo
que é tipo base dos anteriores - Correspondência com os tipos do
java.lang.reflect
:Class
,Member
,Method
eField
. - Tipo
Assembly
como representante da informação de um componente em .Net; -
Assembly::LoadFrom(String path)
-- Carregamento programático de assemblies de umpath
-
Assembly::GetTypes()
-- tipos constituintes de um Assembly; - Informação de um tipo:
BaseType
,GetInterfaces()
; -
GetMembers()
eGetMember(String)
,GetFields()
eGetField(String)
; -
ParameterInfo
e propriedadeParameterType
.
- Definição de propriedades -- resultado da compilação e metadata.
- Auto-Implemented Properties
- API de Reflexão sobre propriedades
- Especificação de um
Logger
para print do estado de um objecto (valor das propriedades de instância);- validar com os tipos
Student
,Point
eAccount
.
- validar com os tipos
- Resolução dos TPCS:
- Realizar em Java a implementação equivalente ao programa App01-hierarchy.cs
- Implemente a classe
Logger
com o método estáticoLog(object)
para print do valor das propriedades de instância.
-
BindingFlags
:Public
,NonPublic
,Instance
,Static
-
MethodInfo
:GetParameters()
eParameterInfo
- Chamada a métodos via reflexão através do
Invoke(object, object[])
- Custom attributes
- Papel dos custom attributes como forma de expressão de intenções.
- Definição de novos atributos:
- Parâmetros de atributos com e sem nome;
- Persistência dos custom attributes na metadata.
-
AttributeUsageAttribute
=> restrição sobre otarget
eAllowMultiple
- Comparação entre custom attibutes e anotações Java
- Inspecção de custom attributes em tempo de execução
-
IsDefined()
eGetCustomAttributes()
- Extensão da API de
Logger
com custom attributes:-
IgnoreAttribute
-- para excluir uma propriedade do métodoLog()
-
LayoutAttribute
-- para customização da apresentação de valor de uma propriedade.
-
- v1 -- passagem de uma
string
com o template de formatação do valor. - v2 -- passagem de
Type
aLayoutAttribute
com a estratégia de formatação --IFormat
. - Reflexão: verificação de compatibilidade entre tipos (Cap 4.3 Essential .Net):
-
IsSubclassOf
eIsAssignableFrom
-
- Criação de instância via reflexão
Activator.CreateInstance(Type)
- Resolução do TPC
- !!!! Alerta aos "custos" da API Reflexão
- !!!!!Alerta para a repetição na obtenção do custom attribute na chamada do método
Format()
!!!! - Passar a obtenção do custom attribute no construtor
- Suporte do
Logger
para Arrays - API de Reflexão para Arrays:
Type::IsArray
,Type::GetElementType()
,Array::GetValue
-
Tipos referência são instanciados com o operador Csharp
new
=> ILnewobj
- Detalhe da instrução
newobj
- responsabilidade na instanciação:- alocação em memória do espaço necessário para alojar o objecto.
- inicialização do header e inicialização do restante espaço a zero
- chamada ao construtor
-
Tipos Valor NÃO são instanciados, mas apenas inicializados:
- Chamada ao construtor sem parâmetros de um tipo valor gera um
initobj
(inicializa os campos a 0/null)
- Chamada ao construtor sem parâmetros de um tipo valor gera um
- Instrução IL
ldloca
- Exemplificação de
ldloca
einitobj
- Sendo Point uma struct então a chamada a
new Point(8, 9)
NÃO gerainitobj
, mas apenas a chamada ao construtor. - Uma struct não pode definir um construtor sem parametros, apenas com parâmetros.
Tipos em runtime (Cap 4.1 Essential .Net)
- Tipos de conversão entre tipos: casting e coerção
- casting implicito vs explicito e análise do codigo IL
- Detalhe do operador IL
castclass
:- recebe dois parâmetros: referência no topo do stack + token do tipo destino da conversão.
- em caso de sucesso deixa a referência no topo do stack
- em caso de insucesso dá excepção.
- operadores Csharp
as
- operadores IL
isinst
- operadores Csharp
is
-
dr["Region"] is DBNull ? null : (string)dr["Region"]
->
isinst + castclass<=>
dr["Region"] as String;
++ eficiente , so tem isinst
- Conversão entre Tipos Referencia e Valor -- boxing e unboxing.
-
Overhead da operação de boxing:
- Alocação de memória;
- Inicialização do header do objecto;
- Cópia do valor para o heap;
- ... e futura libertação de memória pelo Garbage Collector
- Detalhe da operação de unboxing
- Tipo
System.Object
- métodos de instância virtuais (ToString
,Equals
,GetHashCode
eFinalize
) e não virtuais (GetType
); - Tabela de métodos e COREINFO_CLASS_STRUCT
- Evidenciar o
this
como o 1º argumento passado a um método de instância - Detalhe do código assembly gerado para despacho estático (endereço do método) e despacho dinâmico (baseado em offset do método)
- Métodos de instância requerem uma referência para a instância chamada -- target;
- Abordagem do compilador do C# na geração de
call
oucallvirt
-- este último sempre usado para métodos de instância para verificar se o target é diferente denull
. - Demonstração da verificação feita por
callvirt
.
- Modelo de objectos de
System.Reflection.Emit
-
AssemblyBuilder
,ModuleBuilder
,TypeBuilder
,MethodBuidler
eILGenerator
-
- Implementação de um exemplo de geração dinâmica de uma class conforme AssemblyBuilder
- Implementação do logger versão 4
Logger-v4-dynamic.cs
que elimina o uso de reflexão na leitura de valores das propriedades=>
substituiGetter
por implementação dinâmica deIGetter
. - Implementar um exemplo de um
GetterStudentNr
que estendeIGetter
como guião do código IL a gerar. - Abordagem:
- Princípio do uso de Emit: “Usar Reflexão para gerar IL” e "NÃO gerar IL que faz Reflexão”.
- Implementar uma classe em C# hard-coded à imagem do código que se quer
gerar dinamicamente. Compilar e usar esse IL como base. E.g.
GetterStudentNr
,GetterPointX
, ou outro. - Usar ferramenta
PEVerify.exe
para validar a conformidade dos componentes gerados.
- Revisão da tradução de
call
ecallvirt
em despacho estático (DE) ou dinâmico (DD):
static |
instância | virtual |
|
---|---|---|---|
call |
DE | DE (struct) | DE (base) |
callvirt |
-- | DE | DD |
- Demonstração da chamada a um método da base virtual com a instrução
callvirt
, resultando num ciclo infinito.
- Atributos de métodos:
virtual
,new
eoverride
- Exemplos do resultado do layout da tabela de métodos com a utilização dos atributos anteriores
- Estudo de casos de redifinição (
override
) ou "esconder" (new
) de métodos => efeitos no layout da tabela de métodos e resultado na chamada a esses métodos.
- Introdução ao conceito de Sequência, e.g.
[]
,IList
,IEnumerable
, .. - Implementação de funções utilitárias sobre sequências: convert e filter
- Características de uma sequência:
-
Traverse (e.g.
MoveNext()
) + Access (e.g.Current
) - Operações:
- Intermédias, e.g.
map()
,filter()
,limit()
:Seq -> Seq
- Terminais, e.g.
first()
,max()
:Seq -> R | void
- Intermédias, e.g.
- Lazy -- elementos computados on demand
-
Traverse (e.g.
-
Exercício: Dado um
IEnumerable
com as linhas de um ficheiro, listar o primeiro nome de todos os alunos com número superior a 42000 e primeira letraJ
. -
Versão 1: implementar as funções
ConvertToStudents
,ConvertToName
,FilterNameStartsWith
eFilterWithNumberGreaterThan
. -
Versão 2: eliminar a dependência do modelo de domínio criando um único conversor e uma única filtragem:
IEnumerable Convert(IEnumerable src, Function func)
IEnumerable Filter(IEnumerable src, Predicate test)
Definição das interfaces Function
e Predicate
:
public interface Predicate {
bool Invoke(object item);
}
public interface Function {
object Invoke(object item);
}
-
Versão 3: Usar delegate em vez de interface para definição de
Function
ePredicate
.
- Introdução às Expressões Lambda como representação de métodos anónimos:
- resulta na criação de um novo método com um nome atribuído pelo compilador (método anónimo)
- A utilização de expressões lambda evidencia a parametrização de comportamento onde é visível a passagem explícita de código por parâmetro:
Filter(..., item => ((Student) item).nr > 41000 ))
- Separação entre lógica de iteração e lógica do predicado;
- Expressão Lambda = expressão que representa uma implementação concisa de um método anónimo.
- Sintaxe das Expressões Lambda
- Inferência dos parâmetros de tipo da Expressão Lambda
- Distinção entre processamento Eager e Lazy
-
Lazy
=>
on-demand processing -
Lazy
=>
a execução de operações intermédias não processa a sequência. - Detalhe de
IEnumerable
eIEnumerator
-
Versão 4: Implementação Lazy para
Converter
eFilter
- Análise da intercalação da execução das operações na versão Lazy
- Implementação de uma operação
Take()
- Análise do número total de operações executadas.
- Genéricos:
- Classes genéricas – classes com parâmetros de tipo
- Métodos genéricos – métodos com parâmetros de tipo.
- Inferência dos argumentos de tipo a partir dos parâmetros actuais.
- Abordagens diferentes nos genéricos:
- Java:
A<Object>
<=>
A
- .Net:
A<Object>
!=
A
--->
Tipos diferentes e incompatíveis;-
workaround fazer
A<T>
----|>
A
, ou sejaclass A<T> : A {…}
-
workaround fazer
- Java:
- Definição dos métodos genéricos:
Convert<T, R>()
eFilter<T>()
-
Delegates:
Function<T,R>
ePredicate<T>
- Aplicação de EIMI na implementação de
IEnumerable<T>
eIEnumerator<T>
- EIMI - Explicit Interface Method Implementations
- Mais valias na utilização de EIMI em casos de definição dos métodos como privados.
- Resolução do TPC
-
Exercício: Implementar
IEnumerable<T> generate<T>(Func<T> generator)
- Exemplo:
int n = 0;
generate(() => n++); // 0, 1, 2, 3, ...
- Sequências Inifinitas
- instrução
yield
- Vantagens de uma API fluente na legibilidade
-
Extension Methods
=>
não usar nos tipos de nossa autoria. - Métodos utilitários de
System.Linq
- Análise do código resultante da compilação da definição e utilização de um delegate
- Uma instância de um delegate contém internamente um ponteiro para uma função.
- Delegate como uma forma type safe de usar um ponteiro para uma função.
- O método encapsulado num delegate pode ser chamado indirectamente através
desse delegate. E.g. seja
Function f
então podemos fazerf.Invoke(n)
. - Em C# escrever
f.Invoke(n)
é equivalente af(n)
- Campos
_methodPtr
e_target
herdados da classeDelegate
- Instrução IL
ldftn
- Construtor de um tipo delegate recebe os dois parâmetros que inicializarão
os campos anteriores:
-
new Function(App.Foo);
<=>
App.Foo
-
- Diferença de instanciar um tipo delegate para um método estático ou de instância.
Pretende-se desenvolver uma biblioteca para definição e validação de regras
sobre propriedades de objectos. Uma regra é representada pela interface
IValidation { bool Validate(object obj); }
(exemplos de implementações desta
interface: Above18
, NotNull
).
Uma instância de Validator<T>
representa validadores para uma entidade de
domínio de tipo T
, aos quais é possível acrescentar regras de validação para
determinadas propriedade (identificada pelo seu nome), tal como apresentado no
exemplo seguinte:
class Student {
public int Age;
public String Name;
}
Student s = new Student(); s.Age = 20; s.Name = "Anacleto";
Validator<Student> validator = new Validator<Student>()
.AddValidation("Age", new Above18())
.AddValidation("Name", new NotNull());
validator.Validate(s);
- [1] Implemente a classe
Above18
, que retornatrue
se o valor recebido por parâmetro for superior a 18, oufalse
caso contrário. - [2] Implemente a classe
Validator<T>
tendo em conta que o métodoValidate
lança a exceçãoValidationException
, se falhar alguma das regras. - [2] Sem alterar o código escrito anteriormente, acrescente o necessário para
que seja suportada a adição de regras na forma de delegates do tipo
Func<W, bool>
, conforme demonstra o exemplo seguinte. Se a propriedade indicada não for do tipo W, então é lançada a exceçãoTypeMismatchException
. - [2] Adicione o necessário e modifique apenas o método
AddValidation(string name, IValidation val)
de modo a que sobre a mesma propriedade possam ser adicionados vários validadores.
TPC: Realizar o Exercício 2
- Problemas na gestão de memória manual (e.g. com
malloc()
efree()
): memmory leaks e object corruption - Desvantagens: lookup no malloc, Aumento do espaço de endereçamento + fragmentação.
- Gestão automática de memória. VANTAGENS:
- SEM fragmentação;
- RAPIDEZ na alocação de memória.
- Working Set vai ser mais pequeno
- !!!! custo na libertação de memória.
- Algoritmo de GC baseado em gerações e compactação.
- Root references;
- classe
GC
e conjunto de métodos para controlo do Garbage Collector:GC::GetGeneration(object)
GC::Collect()
-
GC::Collect(int gen)
-- até à geraçãogen
GC::GetTotalMemory(bool forceFullCollection)
- Tipos que representam (wrappers) para recursos nativos, tais como: ficheiros, sockets, etc, requerem libertação dos handles para esses recursos.
- Método
Finalize
. - Detalhes do processo de Finalização de objectos:
- Finalization List e Freachable list
GC.WaitForPendingFinalizers
- Interface
IDisposable
e métodoDispose()
. Analogia com a interfaceAutocloseable
do Java - Idioma com utilização do
using
do Csharp. Seu equivalente no Java com try-with-resources