• Nenhum resultado encontrado

Ambientes Virtuais de Execução. Estrutura de Tipos

N/A
N/A
Protected

Academic year: 2021

Share "Ambientes Virtuais de Execução. Estrutura de Tipos"

Copied!
89
0
0

Texto

(1)

Ambientes Virtuais de Execução

(2)

Instâncias de Tipos

Uma instância de um tipo é um objecto ou um valor.

Um

objecto

é uma instância de um tipo num garbage

collected heap.

As instâncias de um

tipo valor

não são objectos:

Não têm cabeçalho do objecto.

Não estão alocados como entidades distintas no garbage

(3)

Membros dos Tipos

Os tipos podem conter membros:

De instância

De tipo (static)

Os membros de um tipo podem ser:

Constantes (membros estáticos)

Campos (Fields)

Métodos

Construtores

de instância

de tipo

Propriedades

Nested Types (são sempre membros static)

Eventos

(4)

Diferentes tipos de membros - Exemplo

public sealed class SomeType {

// Nested class

private class SomeNestedType { }

// Constant, read-only, and static read/write field

private const Int32 c_SomeConstant = 1;

private readonly String m_SomeReadOnlyField = "2";

private static Int32 s_SomeReadWriteField = 3;

// Type constructor

static SomeType() { }

// Instance constructors

public SomeType() { }

public SomeType(Int32 x) { }

//....

(5)

Diferentes tipos de membros - Continuação

// Static and instance methods

public static void Main() { }

public String InstanceMethod() { return null; }

// Instance property

public Int32 SomeProp {

get { return 0; } set { } }

// Instance parameterful property (indexer)

public Int32 this[String s] { get { return 0; } set { } }

// Instance event

public event EventHandler SomeEvent; }

(6)

Outros Membros dos Tipos

Existem outros membros que não fazem parte do CLS

Sobrecarga de operadores

(7)

Visibilidade de um tipo

IL Term

C# Term

Visual Basic Term

Descrição

private

internal

(por omissão)

Friend

Visível apenas dentro do

assembly

(8)

Acessibilidade dos membros de um tipo

IL Term

C# Term

Visual Basic Term

Descrição

Private

private

(default)

Private

Acessível apenas pelos métodos do tipo

Family

protected

Protected

Acessível apenas pelos métodos do tipo

e dele derivados, dentro ou fora do

assembly

Family and

Assembly

(não

suportada)

(não suportada) Acessível apenas pelos métodos do tipo

e dele derivados dentro do assembly

assembly

internal

Friend

Acessível apenas pelos métodos de tipos

definidos no assembly

Family or

Assembly

protected

internal

Protected Friend

Acessível apenas pelos métodos do tipo

e dele derivados dentro ou fora do

assembly e pelos métodos de outros

tipos do assembly

(9)

Acessibilidade de um membro

Para qualquer membro ser acessível, tem de estar

definido num tipo que seja visível.

Ao derivar de uma classe base:

CLR permite que a acessibilidade de um membro redefinido

(overriden) fique menos restritiva.

(10)

Herança

Um tipo

não pode ter

mais que uma

classe base

.

Um tipo pode implementar

qualquer número de interfaces

.

IL Term

C# Term

Visual Basic Term

Description

abstract

abstract

MustInherit

Tipo abstracto

final

sealed

NotInheritable

Não pode ser

estendido.

(11)

Classes estáticas (C#)

Não

podem ser instanciadas;

O compilador não produz nenhum construtor de instância.

Não

podem implementar interfaces.

Só podem definir membros

estáticos

.

O compilador de C# torna este tipo de classes abstract e

(12)

Atributos pré definidos aplicáveis a métodos (1)

CLR Term

C# Term

Visual Basic

Term

Descrição

Static

static

Shared

Método associado ao próprio tipo, não a

uma instância do tipo.

Os membros

estáticos não podem aceder a campos

de instância ou métodos de instância.

Instance

(default)

(default)

Método associado a uma instância do

tipo.

Pode aceder aos campos e métodos

de instância, assim como aos campos e

métodos estáticos.

Virtual

virtual

Overridable

O método mais derivado é invocado

mesmo que o objecto seja convertido

para um tipo base

. Aplica-se apenas a

métodos de instância.

(13)

Atributos pré-definidos aplicáveis a métodos (2)

CLR Term

C# Term

Visual Basic

Term

Descrição

NewSlot

new

(default)

Shadows

O método não deve redefinir um método virtual

definido pelo seu tipo base;

o método esconde o

método herdado

. NewSlot aplica-se apenas a

métodos virtuais.

Override

override

Overrides

Indica que o método está a redefinir um método

virtual definido pelo seu tipo base.

Aplica-se

apenas a métodos virtuais.

Abstract

abstract

MustOverride

Indica que um tipo derivado tem de implementar

um método com uma assinatura que

corresponda a este método abstracto. Um tipo

com um método abstracto é um tipo abstracto.

Aplica-se apenas a métodos virtuais.

Final

sealed

NotOverridable Um tipo derivado

não pode redefinir este

(14)

Invocação de métodos em IL - call

A instrução

call

é utilizada para invocar métodos

estáticos, de instância e virtuais

Quando é usado para invocar um método estático, tem que se

especificar o

tipo

que define o método que o CLR vai invocar.

Quando é usado para invocar um método de instância ou

virtual, é necessário especificar uma variável que se refere ao

objecto.

o

tipo da variável

indica que tipo define o método que o CLR deve

invocar

se o tipo da variável não define o método, os tipos base são

(15)

Invocação de métodos em IL - callvirt

A instrução

callvirt

pode ser utilizada para invocar

métodos de instância ou virtuais.

Quando é usado para invocar um método de instância virtual,

o CLR descobre o tipo actual do objecto que está a invocar o

método.

Invoca o método polimorficamente.

Quando é usado para invocar um método de instância não

virtual, o tipo da variável indica o tipo que define o método

que o CLR vai invocar.

Se a variável que referencia o objecto for null, lança excepção

(16)

Exemplo 1

using System;

public class TesteA{

public static void Main(){

Console.WriteLine( );

Object o = new Object();

o.GetHasCode();

}

}

.method public hidebysig static void Main() cil managed {

.entrypoint

// Code size 15 (0xf) .maxstack 1

.locals init (object V_0) IL_0000: nop

IL_0001: call void [mscorlib]System.Console::WriteLine()

IL_0006: nop

IL_0007: newobj instance void [mscorlib]System.Object::.ctor() IL_000c: stloc.0

IL_000d: ldloc.0

IL_000e: callvirt instance int32

[mscorlib]System.Object::GetHashCode()

IL_0013: pop IL_0014: ret

(17)

Exemplo 1

using System;

public class TesteA{

public static void Main(){

Object o = new Object();

o.GetType();

}

}

.method public hidebysig static void Main() cil managed {

.entrypoint

// Code size 15 (0xf) .maxstack 1

.locals init (object V_0) IL_0000: nop

IL_0001: newobj instance void [mscorlib]System.Object::.ctor() IL_0006: stloc.0

IL_0007: ldloc.0

IL_0008: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()

IL_000d: pop IL_000e: ret

(18)

Métodos de instância não virtuais em C#

Em C#, nas chamadas aos

métodos de instância não virtuais

para tipos referência é utilizada a instrução

callvirt

verfica que o objecto que está a fazer esta invocação não é null. Se

for lança excepção do tipo NullReferenceException

Ex:

using System;

public sealed class Program{

public Int32 GetFive() { return 5;}

public static void Main( ){

Program p = null;

Int32 x = p.GetFive();

}

(19)

Métodos virtuais – instrução call

Por vezes o compilador usa a instrução

call

para

invocar métodos virtuais

Ex:

internal class SomeClass{

public override String toString(){

return base.toString()

}

}

(20)

Exemplos

using System;

class A{

public void F(){ Console.WriteLine("A.F"); }

public virtual void G(){ Console.WriteLine( " A.G");}

}

class B: A{

public void F(){ Console.WriteLine("B.F");}

public override void G() { Console.WriteLine("B.G");}

}

class Test{

static void Main(){

B b = new B(); A a = new B();

a.F(); b.F(); a.G(); b.G();

}

(21)

Exemplos

using System;

class A{

public void F(){ Console.WriteLine("A.F"); }

public virtual void G(){ Console.WriteLine( " A.G");}

}

class B: A{

public void F(){ Console.WriteLine("B.F");}

public override void G() { Console.WriteLine("B.G");}

}

class Test{

static void Main(){

B b = new B(); A a = new B();

a.F(); b.F(); a.G(); b.G();

}

}

A.F

B.F

B.G

B.G

(22)

Métodos com número variável de argumentos

class TParams {

static void showArgs(params object[] args) {

foreach(object arg in args)

Console.WriteLine(arg.ToString());

}

static void Main() {

showArgs("olá", "admirável", "mundo", "novo!");

}

}

(23)

Passagem de parâmetros: por valor

Passagem por valor:

Através

da cópia do conteúdo da variável;

Comportamento por omissão.

Caller

Callee

x = 83

y = addr

a = 83

b = addr

“Don”

38

f(int a, Patient b)

f(x,y)

(24)

Passagem de parâmetros: por referência

Passagem por referência:

Através de ponteiro managed para a variável;

Em IL indicado por & e em C# por ref.

Caller

Callee

x = 83

y = addr

a = addr

b = addr

“Don”

38

f(ref int a, ref Patient b)

(25)

ref versus out

using System;

public sealed class Program{

public static void Main(){

Int32 x;

GetVal(

out

x );

Console.WriteLine(x);

}

private static

void GetVal(

out

Int32 v){

v

= 10;

}

}

using System;

public sealed class Program{

public static void Main(){

Int32

x

= 5;

GetVal(

ref

x );

Console.WriteLine(x);

}

private static

void GetVal(

ref

Int32 v){

v = 10;

}

}

(26)

ref versus out

//Pseudo - código

using System; Using System.IO;

public sealed class Program{ public static void Main(){ FileStream fs;

StartProcessingFiles( out fs );

for( ; fs !=null; ContinueProcessingFiles( ref fs ) ){ fs.Reader( . . . ); } }

private static void StartProcessingFiles(out FileStream fs ){ fs = new FileStream( ... );

}

private static void ContinueProcessing( ref FileStream fs ){ fs.Close();

if(noMoreFileToProcess) fs = null; else fs = new FileStream( ... ) }

(27)

class Utils {

public static void swap(ref object a, ref object b) {

object aux=a;

a=b;

b=aux;

}

}

Parâmetros ref e a compatibilidade de tipos

Sejam duas referências para string:

Qual o problema do seguinte código?

string s1,s2;

(28)

Construtores

CLR suporta:

Construtores de tipo

Utilizados para estabelecer o

estado inicial de um tipo

.

É um método estático com um nome especial →

.cctor

.

O CLR garante a chamada ao construtor de tipo antes de qualquer

acesso a um campo de tipo.

Construtores de instância

Utilizados para estabelecer o

estado inicial de uma instância de um

tipo

.

(29)

Iniciação de tipos

Em CLR, um construtor de tipo pode ser aplicado a

interfaces, tipos referência e tipos valor

Não é permitido em C# aplicar construtores de tipos a

interfaces.

Por omissão os tipos não têm um construtor de tipos definido.

Só pode ser definido, no máximo um construtor de tipo por

cada tipo.

Têm de ser privados

Em C# a acessibilidade private é colocada automaticamente

O método não recebe parâmetros;

(30)

Iniciação de tipos - Exemplos

.

Os campos com expressões de iniciação na sua definição

, são os

primeiros a ser iniciados pelo construtor

internal sealed class SomeRefType{

static SomeRefType(){

//. . .

}

}

internal struct SomeValType{

static SomeValType(){

//. . .

}

}

internal sealed class SomeType{

private static Int32 s = 5;

static SomeRefType(){

s = 10;

}

(31)

Políticas de iniciação de tipo

O CLR garante a chamada ao construtor de tipo antes de

qualquer acesso a um campo de tipo;

Políticas de iniciação de tipos:

Imediatamente antes do primeiro acesso a qualquer

membro – usada em C# quando

há construtores de tipo

;

Em qualquer altura desde que antes do primeiro acesso a um

campo de tipo (atributo de Metadata beforefieldinit

-

política em C# quando

não for definido explicitamente

(32)

Construção de objectos

Quando se cria uma instância de um reference type:

É

reservado

, no managed heap

, um bloco de memória com o

número de bytes necessários para armazenar o objecto do

tipo especificado.

Inicia os membros overhead do objecto

. Cada instância tem

associados dois membros adicionais usados pelo CLR na

gestão do objecto.

O primeiro membro é um apontador para a tabela de métodos do

tipo;

O segundo é o SyncBlockIndex (usado na sincronização).

É chamado o construtor

de instância do tipo.

(33)

Construção de objectos

O CLR requer que todos os objectos sejam criados usando o

operador new

emite a instrução IL newobj.

EX: Employee e = new Employee("ConstructorParam1");

Os construtores de instância nunca são herdados

Não lhes pode ser aplicado os modificadores virtual, new,

override, sealed e abstract

Em C#, se uma classe não definir explicitamente um construtor, o

compilador gera um por omissão.

public class SomeType{

// ... Sem construtor de instâncias

}

public class SomeType{

public SomeType() : base () {

}

// ...

}

(34)

Construção de objectos – keyword this

Nota:

Embora a maioria das linguagens compilem os construtores de forma

a que seja chamado o construtor do tipo base, o CLR não obriga à

existência desta chamada.

private sealed class SomeType{

private Int32 m_x;

private String m_s;

public SomeType( ){

m_x = 5;

m_s= “Ola”;

}

public SomeType( Int32 x) : this ( ){

m_x = 10;

}

}

(35)

Iniciação de instâncias

Construtor de instância:

Tem nome especial → .ctor

Podem existir várias sobrecargas.

Comportamento do construtor:

1.

Inicia os campos que têm expressões de iniciação na sua definição;

2.

Chama o construtor da classe base;

(36)

Sobrecarga de métodos

Podem ser sobrecarregados se diferirem em:

Número de parâmetros;

Tipo dos parâmetros;

Tipo de retorno; (não em C#)

Passagem de parâmetro por valor ou referência.

As regras CLS permitem sobrecarga se os métodos

(37)

O tipo valor Ponto em C#

(com redefinição de

Equals)

public struct Ponto {

public int x, y;

public Ponto(int x, int y) { this.x=x; this.y=y; }

public override bool Equals(object obj) {

if (obj == null) return false;

if (!(obj is Ponto)) return false;

return Equals( (Ponto) obj);

}

public bool Equals(Ponto p) { return x== p.x && y == p.y; }

public override int GetHashCode() { return x^y; }

public override string ToString() {

return String.Format("({0},{1})", x, y);

}

(38)

Desambiguar colisões de nomes

Campos de tipo:

Através do nome do tipo pretendido.

Campos de instância:

Através do uso das palavras this e base;

Métodos:

2 políticas:

Hide-by-name – esconde todos as sobrecargas de métodos com o mesmo

nome; (C++)

Hide-by-signature – esconde o método com igual assinatura. (C#)

Na CLS não existe colisão em nomes que variam apenas na capitalização

(39)

Operador new - Exemplo

using System;

class A {

public virtual void F() { Console.WriteLine("A.F"); } }

class B: A {

public override void F() { Console.WriteLine("B.F"); } }

class C: B

{

new public virtual void F()

{ Console.WriteLine("C.F"); } }

class D: C

{

public override void F() { Console.WriteLine("D.F"); } }

class Test {

static void Main() {

D d = new D();

A a = d; B b = d; C c = d;

a.F(); b.F(); c.F(); d.F();

B.F

B.F

D.F

D.F

As classes C e D

contêm

dois

métodos com a

mesma assinatura

!

D

redefine o

método

introduzido

em C

(40)

Operador new - Exemplo

using System;

class A {

public virtual void F() {} }

class B: A {

new private void F() {} //

Esconde A.F em B

}

class C: B {

public override void F() {} //

Ok, redefine A.F

(41)

Atributos aplicáveis a campos

O CLR permite que um campo seja marcado como static,

initonly ou static e initonly.

O C# suporta a combinação dos dois.

IL Term

C# Term

Visual Basic Term

Description

static

static

Shared

Campo de tipo

initonly

readonly

ReadOnly

(42)

Constantes – C#

É um símbolo ao qual é atribuído a um valor que nunca se altera.

O valor a atribuir têm que ser determinado em tempo de

compilação, logo,

apenas

podem ser

definidas constantes de

tipos primitivos da linguagem

.

O

compilador

guarda o valor da constante na Metadata do

módulo (como um campo

estático literal

)

não é alocada memória em tempo de execução

Não é possível obter o endereço duma constante nem passá-la por

referência.

Por levantar problemas de versões, só devem ser usadas quando

existe certeza que o seu valor é imutável (p.ex. Pi, MaxInt16,

MaxInt32, etc.).

Exemplo em C#

(43)

Campos readonly – C#

Campos readonly

Só podem ser afectados durante a construção da instância do tipo onde

estão definidos

Um campo static readonly é definido em run time.

Uma constante é definida em compile time.

Em C#:

readonly Int32 SomeReadOnlyField = 2;

O campo é marcado com o atributo InitOnly

(44)

Propriedades

As propriedades permitem ao código fonte invocar um

método utilizando uma sintaxe simplificada.

Existem dois tipos de propriedades:

Propriedades sem parâmetros

Propriedades com parâmetros

(45)

Propriedades sem parâmetros

public sealed class Employee{

private String m_Name;

private Int32 m_Age;

public String Name {

get { return( m_Name); }

set { m_Name = value; }

}

public Int32 Age {

get { return( m_Age); }

set { if ( value < 0 )

throw new

ArgumentOutOfRangeException(‚value‛,

value.ToString(),

‚O valor tem de ser maior ou igual a 0‛);

m_Age = value;}

}

}

Employee e = new Employee();

String empName = e.Name;

e.Age = 41;

Int32 i = e. Age;

e.Age = -5;

(46)

Propriedades sem parâmetros

Cada propriedade tem um

nome e um tipo

;

Não

pode existir

sobrecarga

de propriedades;

Acedidas através de um nome ou um acesso de membro

Pode ser um membro

estático ou de instância

O get accessor de uma propriedade não tem parâmetros

O set accessor de uma propriedade contêm

(47)

Propriedades sem parâmetros - Exemplo 2

public sealed class Employee{

private String m_Name;

private Int32 m_Age;

private static Int32 nR_Employees;

public String Name {

get { return(m_Name); }

set { m_Name = value; }

}

public Int32 Age {

get { return( m_Age); }

set { if ( value < 0 ) throw new ArgumentOutOfRangeException(‚value‛,

value.ToString(),

‚O valor tem de ser maior ou igual a 0‛);

m_Age = value;}

}

public static Int32 NrEmployees{

get { return(nR_Employees); }

}

(48)

Propriedades estáticas e de instância

using System;

using CTSTester.Properties; namespace CTSTester {

namespace Properties {

public class TypeWithProps { private static int aTypeField;

public string AnInstanceProperty {

get { return "instance property"; } }

public static int ATypeProperty { get { return aTypeField; } set { aTypeField = value; } }

} }

class TestProperties {

public static void Main() {

TypeWithProps mt = new TypeWithProps();

System.Console.WriteLine(mt.AnInstanceProperty); System.Console.WriteLine(TypeWithProps.ATypeProperty); TypeWithProps.ATypeProperty = 30; System.Console.WriteLine(TypeWithProps.ATypeProperty); } } }

(49)

Propriedades estáticas e de instância (IL de Main)

.method public hidebysig static void Main() cil managed { .entrypoint

// Code size 45 (0x2d) .maxstack 2

.locals init ([0] class CTSTester.Properties.TypeWithProps mt)

newobj instance void CTSTester.Properties.TypeWithProps::.ctor() stloc.0

ldloc.0

callvirt instance string

CTSTester.Properties.TypeWithProps::get_AnInstanceProperty()

call void [mscorlib]System.Console::WriteLine(string) call int32

CTSTester.Properties.TypeWithProps::get_ATypeProperty()

call void [mscorlib]System.Console::WriteLine(int32) ldc.i4.s 30

call void

CTSTester.Properties.TypeWithProps::set_ATypeProperty(int32) call int32

CTSTester.Properties.TypeWithProps::get_ATypeProperty()

call void [mscorlib]System.Console::WriteLine(int32) ret

(50)

Propriedades com parâmetros

Identificado pela sua

assinatura

.

Acedido através de um acesso de um elemento.

Tem de ser um

membro de instância

.

O get accessor de um indexer tem o

mesma

lista de parâmetros formais

que um indexer.

O set accessor de um indexer tem a

mesma lista

de parâmetros formais de

um indexer, assim

(51)

Indexers (criação)

class IndexerClass {

private int [] myArray = new int[100];

public int this [int index] {

get {

if (index < 0 || index >= 100) return 0;

else return myArray[index];

}

set {

if (!(index < 0 || index >= 100))

myArray[index] = value; }

}

}

(52)

Indexers (Utilização)

public class MainClass {

public static void Main() {

IndexerClass b = new IndexerClass();

b[3] = 256;

b[5] = 1024;

for (int i=0; i<=10; i++) {

Console.WriteLine("Element #{0} = {1}", i, b[i]);

}

}

}

(53)

Classes parciais – C#

Objectivo:

Separar o código gerado automaticamente do código escrito pelo

programador

Uma classe pode ser dividida em partes, em que cada parte

corresponde a uma implementação parcial da classe.

Todas as partes da classe devem estar disponíveis no momento

da compilação

gera uma única classe em representação intermédia

classe reside num único assembly

(54)

Classes parciais – C#

Aspectos acumulativos de uma classe:

Campos

Métodos

Propriedades

Indexadores

Interfaces implementadas

Aspectos não acumulativos:

Classe base

Tipo-valor ou tipo-referência

Visibilidade

As diversas partes de uma mesma classe devem concordar nos

(55)

Enumerados

Os

enumerados

permitem definir especializações de tipos

integrais que não adicionam campos, mas simplesmente

restrigem o espaço de valores de um tipo integral específico.

O tipo enumerado é um

tipo valor

em que o tipo base é

System.Enum

.

Os enumerados têm um

segundo tipo subjacente

que irá ser

usado para a representação dos dados da enumeração

Se não for especificado nenhum, é assumido pelo compilador C# o

tipo

System.Int32

.

O Tipo

System.Char

não pode ser utilizado.

Os enumerados pode ser representados em formas boxed e

unboxed.

(56)

Enumerados

.class private auto ansi sealed Geometry.EstacoesDoAno

extends [mscorlib]System.Enum {

.field public specialname rtspecialname int32 value__

.field public static literal valuetype

EstacoesDoAno Primavera = int32(0x00000000)

.field public static literal valuetype

EstacoesDoAno Verao = int32(0x00000001)

.field public static literal valuetype

EstacoesDoAno Outono = int32(0x00000002)

.field public static literal valuetype

EstacoesDoAno Inverno = int32(0x00000003)

} // end of class Geometry.EstacoesDoAno

enum EstacoesDoAno {

Primavera, Verao, Outono, Inverno

};

(57)

Exemplo - Continuação

using System;

internal enum Color{ White,

Red, Green, Blue, Orange }

public class Program{

public static void Main(){

Console.WriteLine(Color.Format(typeof(Color),3,"G")); Color c = (Color) Enum.Parse(typeof(Color), "White"); Console.WriteLine(c);

Console.WriteLine("{0:D} \t {0:G}",c);

c = (Color) Enum.Parse(typeof(Color), "white",true); Console.WriteLine(c.ToString("G")); Console.WriteLine(Enum.IsDefined(typeof(Color),"red")); }

Blue

White

0 White

White

False

(58)

O tipo Enum (excerto)

int CompareTo(object target) Compara esta instância com o objecto especificado e retorna uma indicação dos seus valores relativos.

static string Format(Type enumType, object value,

string format)

Converte o valor especificado de um tipo enumerado especificado para a sua representação equivalente sob a forma de string, de acordo com o formato especificado. static string GetName(Type enumType,

object value)

Retorna o nome da constante na enumeração especificada que tem aquele valor especificado.

static string[] GetNames(Type enumType) Retorna um array com os nomes das constantes na enumeração especificada.

static Type GetUnderlyingType(Type enumType)

Retorna o tipo subjacente da enumeração especificada. static Array GetValues(Type enumType) Retorna um array com os valores das constantes numa

enumeração especificada. static bool IsDefined(Type

enumType,object value)

Retorna true se e só se uma constante com um valor especificado existe numa enumeração especificada. static object Parse(Type

enumType,string value)

Converte a representação sob a forma de string do nome ou valor numérico de uma ou mais constantes enumeradas para um objecto enumerado equivalente.

(59)

Interfaces

Keyword interface (para definição de “Interface Types”)

Para especificação de contratos, isto é, conjunto de operações suportadas

As interfaces suportam herança múltipla de outras interfaces.

Não podem conter campos de instância nem métodos de

instância com implementação.

Todos os métodos de instância têm, implicitamente, os

atributos public e virtual.

Por convenção, o nome das interfaces começa pelo carácter „I‟

(60)

Exemplo – interface A

public interface A{

void GetA();

}

.class interface public abstract auto ansi A

{

.method public hidebysig newslot abstract virtual

instance void GetA() cil managed

{

} // end of method A::GetA

(61)

Interface IComparable

public interface IComparable<T>{

Int32 CompareTo(T other);

}

public class Point : IComparable<Point>{

private Int32 x,y;

public Point( Int32 x, Int32 y){

this.x=x;

this.y=y;

}

public Int32 CompareTo(Point other){

return Math.Sign(Math.Sqrt(x*x+y*y) -

Math.Sqrt(other.x*other.x + other.y*other.y)

);}

(62)

Interfaces

Em C# a implementação de uma interface resulta, por

omissão, em métodos

sealed

.

O que não acontece se o método na classe for declarado

como virtual.

Exemplo:

Em C#

public Int32 CompareTo(Point other){...}

Em IL:

.method public hidebysig newslot virtual

final

instance int32 CompareTo(class Point

other) cil managed

(63)

Interface Type

Linguagem C# - Excerto do modelo de tipos

(interfaces)

Object ValueType Types Reference Types Interfaces Legenda BCL Namespace System User defined

...

...

(64)

Interfaces – Exemplo 2

using System;

using System.Collections;

public class Program{

public static void Main(){

String s="AVE";

ICloneable cloneable = s;

IComparable comparable = s;

IEnumerable enumerable = (IEnumerable) comparable;

}

}

Porque o tipo do objecto

(65)

Interfaces (pré-genéricos) de enumeração - IEnumerable, IEnumerator e C#

foreach

ArrayList vals = new ArrayList(new Int32[]{ 1, 4, 5 }); foreach(Int32 v in vals) Console.WriteLine(v);

public interface System.Collections.IEnumerable { IEnumerator GetEnumerator();

}

public interface System.Collections.IEnumerator { Boolean MoveNext();

void Reset();

Object Current { get; } }

ArrayList vals = new ArrayList(new Int32[]{ 1, 4, 5 }); IEnumerator itr = vals.GetEnumerator();

...

while(itr.MoveNext()) Console.WriteLine((Int32)itr.Current); ...

(66)

ICloneable

Implementada por tipos que permitam “clonagem” de instâncias

Políticas de “clonagem”:

Cópia superficial (shallow copy)

Método Object MemberwiseClone() de System.Object

Cópia total (deep copy)

public interface System.ICloneable {

Object Clone();

(67)

Interfaces e Value Types

Os Value Types derivam obrigatoriamente e directamente de

System.ValueType

ou de

System.Enum

mas podem implementar 0 ou

mais interfaces (via boxing)

A conversão entre um Value Type e as interfaces por ele implementadas está

sujeita às regras de conversão entre Value Types e Reference Types (boxing e

unboxing)

public struct Point : System.IComparable {

public Int32 CompareTo(Object o) { return ... } }

...

Point p1 = new Point(1,2), p2 = new Point(2,1);

p1.CompareTo(p2); // boxing em p2

((System.IComparable)p1).CompareTo(p2); // boxing em p1 e p2

(68)

Implementação Explícita de interfaces

Exemplo:

interface IDimensions { float Length(); float Width(); }

class Box : IDimensions {

float lengthInches; float widthInches; public Box(float length, float width) {

lengthInches = length; widthInches = width; }

float IDimensions.Length() { return lengthInches; } float IDimensions.Width() { return widthInches; } public static void Main() {

Box myBox = new Box(30.0f, 20.0f);

IDimensions myDimensions = (IDimensions) myBox;

System.Console.WriteLine("Length: {0}", myDimensions.Length()); System.Console.WriteLine("Width: {0}", myDimensions.Width()); } }

Uma classe que implementa uma interface pode explicitamente implementar um

membro dessa interface.

Quando um membro é explicitamente implementado, não pode ser acedido

através uma instância da classe.

(69)

Implementação Explícita de interfaces(2)

A implementação

explícita de um

membro de

interface pode ser

útil, por exemplo,

em cenários de

implementação de

duas interfaces

que partilham

métodos com a

mesma assinatura

interface IEnglishDimensions { float Length(); float Width(); }

interface IMetricDimensions { float Length(); float Width(); }

class Box : IEnglishDimensions, IMetricDimensions { float lengthInches; float widthInches;

public Box(float length, float width) {

lengthInches = length; widthInches = width;

float IEnglishDimensions.Length() { return lengthInches; } float IEnglishDimensions.Width() { return widthInches; }

float IMetricDimensions.Length() { return lengthInches * 2.54f; } float IMetricDimensions.Width() { return widthInches * 2.54f; } public static void Main() {

Box myBox = new Box(30.0f, 20.0f);

IEnglishDimensions eDimensions = (IEnglishDimensions) myBox; IMetricDimensions mDimensions = (IMetricDimensions) myBox;

System.Console.WriteLine("Length(in): {0}", eDimensions.Length()); System.Console.WriteLine("Length(cm): {0}", mDimensions.Length());

(70)

Implementação explícita de Interfaces

public interface IA { void Method1();

void Method2(Int32 val); }

public class Impl : IA { public void Method1(){ ..

}

void IA.Method2(Int32 val){ ..

} }

Os tipos que implementam as interfaces podem dar uma implementação

explícita de alguns métodos da interface.

(71)

Implementação explicita de interfaces

Um tipo exacto (classe) pode optar por esconder a

implementação de um método da sua “interface” pública

AClass a = new AClass(); a.Draw(); // AClass.Draw

IWindow iw = (IWindow) a; iw.Draw(); // IWindow.Draw public interface IWindow { void Draw(); }

public interface IArtist[ void Draw(); }

public class AClass : IWindow , IArtist {

// apenas visivel com uma referência para ICowboy void IWindow.Draw() { }

// apenas visível com uma referência para IArtist void IArtist.Draw() { }

// visível com uma referência para aClass public void Draw() { }

(72)

Implementação explícita de Interfaces (II)

A implementação explícita de interfaces permite evitar operações de box e

unbox na invocação de métodos de implementação de interfaces em tipos

valor, usando o idioma mostrado a seguir:

struct Val : ICloneable { public int v;

object ICloneable.Clone() { return MemberWiseClone(); }

public Val Clone() { return new Val(v);

}

}

Permite:

Val v = new Val(5); Val v1 = v.Clone(); Sem operações de box e unbox Usado quando:

ICloneable ic = new Val(5); Val v1 = (Val) ic.Clone();

(73)

Class Type Interface Type

Linguagem C# - Modelo de tipos revisitado

Struct Type Enum Type Object object ValueType String string Array

Enum Double double Single float Int64 long Int32 int Int16 short Sbyte sbyte

Char char Boolean bool UInt64 ulong UInt32 uint UInt16 ushort Byte byte Array Type Legenda BCL Namespace System User defined

(74)

Tabela de métodos

Quando um tipo armazenado no CLR, uma

tabela de

métodos

é inicializada para o tipo.

A tabela de métodos no CLR tem entradas para métodos de

instância e estáticos.

A primeira região é usada para os métodos virtuais (declarados no

tipo actual, nos tipos base ou interfaces)

Slots iniciais irão corresponder aos métodos virtuais declarados pelos tipo

base

;

Slots seguintes irão corresponder aos novos métodos virtuais

introduzidos

pelo tipo;

Exemplo:

Como System.Object é o tipo base de todos os tipos concretos e tem

4 métodos virtuais,

os primeiros slots de todas as tabelas de métodos

correspondem a esses 4 métodos

(75)

Atributos de metadata e métodos virtuais

Atributos

de

metadata

Presente

Ausente

virtual

O índice na tabela de métodos

está na região dos métodos

virtuais.

O índice na tabela de métodos está

na região dos métodos não

virtuais.

newslot

Aloca um novo índice na tabela de

métodos

Re-utiliza o índice do método do

tipo base, se possível.

abstract

Requere substituição no tipo

derivado.

Permite substituição no tipo

derivado

final

Proíbe subtituição no tipo

derivado.

Permite substituição no tipo

derivado

(76)

Tabela de interfaces

Quando um tipo armazenado no CLR, uma

tabela de

interfaces

é inicializada para o tipo.

A tabela de interfaces tem entradas para cada interface que o

(77)

I

nformação de tipo em tempo de execução (RTTI)

campos htype

Interface table

htype (IA)

htype (IB)

pItfTable

pBase

pItfTable

pBase

object reference

(T1) RTTI

(Object) RTTI

htype (IB)

null

interface IA { }

interface IB { }

class T1 : IA, IB { }

class T2 : T1, IB { }

pItfTable

pBase

(T2) RTTI

instância de T2 Method table Method table Method table

Interface table

(78)

Arrays

Todos os tipos de arrays derivam implicitamente da classe abstracta

System.Array.

Exemplos:

Int32[ ] myIntegers = new Int32[100];

Point[ ] myPoints = new Point[10];

Double[ , ] myDoubles = Double[10,20];

int[] numbers = new int[5] {1, 2, 3, 4, 5};

int[] numbers = new int[] {1, 2, 3, 4, 5};

int[] numbers = {1, 2, 3, 4, 5};

int[,] numbers = { {1, 2}, {3, 4}, {5, 6} };

//jagged arrays (arrays de arrays)

Point[ ][ ] myPoligon = new Point[3][ ];

myPoligon[0] = new Point[10];

myPoligon[1] = new Point[20];

myPoligon[2] = new Point[30];

(79)

Conversão de Arrays

CLR permite a conversão do tipo dos elementos do array

origem para o tipo pretendido

Ambos os arrays têm de ter as mesmas dimensões

Tem de existir uma conversão implícita ou explícita do tipo do

elemento do array de origem para o tipo do elemento do

array destino

FileStream[ ] s1 = new FileStream[10];

Object[ ] o1= s1;

FileStream[ ] s2 = (FileStream[ ]) o1;

A conversão dos arrays de um tipo para o outro

(80)

covariância em arrays

Seja o seguinte código:

string[] tabStrings = new string[] { "str1", "str2", "str3" };

Console.WriteLine("Size={0}", tabStrings.Length);

foreach( string str in tabStrings )

Console.WriteLine(str);

// E o código seguinte?

object[] tabObjects = tabStrings; // covariância em arrays

tabObjects[2]= new object(); // problemas?

(81)

Arrays com limite inferior diferente de zero

É possível criar este tipo de arrays recorrendo à método:

public static

Array CreateInstance(Type elementType, int[] lengths, int[] lowerBounds)

Exemplos:

Array a = Array.CreateInstance(typeof(String),new Int32[] {0} , new Int32[] {1}) Array b;

b= Array.CreateInstance(typeof(String),new Int32[] {0,0} , new Int32[] {1,1})

O tipo do array

Um array unidimensional que

contém o tamanho de cada

dimensão do array a criar

Array unidimensional que contém

o limite inferior (o índice de início)

de cada dimensão do array a criar

(82)

Interfaces implementadas pela classe Array

interface System.Collections.ICollection +CopyTo(array:Array,index:int):void Count:int SyncRoot:object IsSynchronized:bool interface System.Collections.IList +Add(value:object):int +Clear():void +Contains(value:object):bool +IndexOf(value:object):int +Insert(index:int,value:object):void +Remove(value:object):void +RemoveAt(index:int):void +this(index:int):object IsFixedSize:bool IsReadOnly:bool Array interface System.Collections.IEnumer able +GetEnumerator():IEnumerator interface System.Collections.ICloneable +Clone():object

(83)

O tipo Array - propriedades

Length

Gets a 32-bit integer that represents the total number of elements in all the dimensions of the Array.

LongLength Gets a 64-bit integer that represents the total number of elements in all the dimensions of the Array.

Rank

Gets the rank (number of dimensions) of the Array.

Para além das propriedades relacionadas com a implementação

das interfaces IList, IEnumerable e IClonable

(84)

O tipo Array – métodos publicos (I)

static int BinarySearch(Array, object)

Overloaded. Searches a one-dimensional sorted Array for a value, using a binary search algorithm.

static void Copy(Array, Array, int)

Overloaded. Copies a section of one Array to another Array and performs type casting and boxing as required.

static Array CreateInstance(Type, int)

Overloaded. Initializes a new instance of the Array class. int GetLength( int dimension)

Gets a 32-bit integer that represents the number of elements in the specified dimension of the Array.

int GetLowerBound(int dimension) Gets the lower bound of the specified dimension in the Array.

Para além dos métodos relacionados com a implementação

das interfaces IList, IEnumerable e IClonable e dos

definidos em object

(85)

O tipo Array – métodos publicos (II)

public int GetUpperBound( int dimension) Gets the upper bound of the specified dimension in the Array.

public object GetValue(int) Overloaded. Gets the value of the specified element in the current Array. The indexes are specified as an array of 32-bit integers.

public void Initialize()

Initializes every element of the value-type Array by calling the default constructor of the value type.

public static void Reverse(Array)

Overloaded. Reverses the order of the elements in a one-dimensional Array or in a portion of the Array.

public void SetValue(object, int) Overloaded. Sets the specified element in the current Array to the specified value.

(86)

Acesso a array não seguro

O acesso a array não seguro permite aceder

A elementos de um objecto array managed (alojado no heap)

A elementos de um array que está alojado no unmanaged heap

A elementos de um array que está alojado na stack

Para alojar um array na stack utiliza-se a instrução stackalloc

Apenas se podem criar arrays unidimensionais, cujo tipo de elementos

seja tipo valor, com limite inferior zero (zero-based arrays)

O tipo valor poderá conter campos de tipo referência

(87)

Acesso a array não seguro – Exemplo 1

//. . .

public static void Main(){ StackallocDemo(); }

private static void StackallocDemo( ){

unsafe{

const Int32 width = 20 ;

Char * pc =

stackalloc

Char [ width ];

String s =‚ Ola Mundo ‚;

for(Int32 index = 0; index <width; index++){

pc[width – index – 1] = (index <s.Length) ? s[index] : ‘.’;

}

Console.WriteLine(new String(pc,0,width));

}

(88)

Acesso a array não seguro – Exemplo 2

//. . .

public static void Main{ InlineArrayDemo(); }

internal unsafe struct CharArray {

public fixed Char Characters[ 20 ]; }

private static void InlineArrayDemo( ){

unsafe

{

CharArray ca;

const Int32 width = 20 ;

String s =‚Ola Mundo‚;

for(Int32 index = 0; index <width; index++){

ca.Characters[width – index – 1] = (index <s.Length) ? s[index] : ‘.’;

}

Console.WriteLine(new String(ca.Characters,0,width));

}

(89)

Importante O CLR não tem a noção de namespaces. Quando acede a um tipo, o CLR necessita de

conhecer o nome completo do tipo e qual o assembly que contém a respectiva definição.

Namespaces e Assemblies

Os namespaces permitem o agrupamento lógico de tipos relacionados. Este mecanismo é usado pelo

programadores para localizarem facilmente um determinado tipo. Por exemplo, o namespace

System.Collections define o grupo de tipos colecção, e o namespace System.IO define o grupo de tipos

relacionados com as operações de I/O. A seguir apresenta-se código que constrói um objecto do tipo

System.IO.FileStream e um objecto do tipo System.Collections.Queue:

class App {

static void Main() {

System.IO.FileStream fs = new System.IO.FileStream(...); System.Collections.Queue q = new System.Collections.Queue(); }

} // ou

using System.IO; // Try prepending "System.IO"

using System.Collections; // Try prepending "System.Collections" class App {

static void Main() {

FileStream fs = new FileStream(...); Queue q = new Queue();

} }

Referências

Documentos relacionados

5.4 Cópia do curriculum lattes (gerado na plataforma http://lattes.cnpq.br ); 5.5 Cópia do(s) documento(s) da titulação e experiência exigida para a vaga. 5.6 Toda a

O artigo aborda como o financiamento e a circulação de produções artísticas se apresentam como pauta de interesse para militantes conservadores no contexto recente,

Este Termo de Referência não tem por finalidade tratar da formatação do Produto Turístico, e sim proporcionar aos empresários e gestores do circuito o conhecimento dos aspectos que

Os Encarregados de Educação podem aceder ao Certificado de Classificação por Escola e/ou ao Certificado de Classificação Nacional a partir da listagem dos resultados por

Os objetivos específicos são os seguintes: (a) iniciar o debate sobre organizações internacionais a partir do conceito de Sociedade Internacional da Escola

Viabilizar a capacitação para suspeição do câncer infantojuvenil em todos os pontos de atenção da rede municipal (Atenção Primária, Rede de Urgência e Emergência,

Tiveram seu uso bem fundamentado, ape- nas no ambiente da intervenção coronária, percutânea, e, em menor grau, em pacientes de alto risco (especi- almente diabéticos), mesmo

a) Pagar pontualmente os valores que sejam de sua responsabilidade, cabendo-lhe, também, o pagamento de tributos que recaiam sobre os serviços que prestar. b) Manter