Documente Academic
Documente Profesional
Documente Cultură
1
21.01.2007
Curs 3
Atribute. Interfete.
Atribute
Ideea de baza: autodescrierea componentelor. Astfel compilatorul si CLR pot citi aceste
informatii. De asemenea dezvoltatorul componentei are toate informatiile despre componenta
intr-un singur loc.
Atributele ne furnizeaza informatiile asociate cu tipul definit in C#. Important e ca aceasta
informatie poate fi definita de dezvoltatorul tipului si nu este statica, legata de limbaj.
Aceasta asociere de informatie urmeaza aceleasi principii folosite in dezvoltarea XML.
Putem crea un atribut bazat pe orice informatie dorim. Exista un mecanism standard pentru
definirea atributelor si pentru interogarile membrului sau tipului la run time.
Toate atributele, preconstruite sau definite de utilizator, sunt derivate direct sau indirect din
System.Attribute.
Atributele mostenesc o anumita comportare implicita:
atributul poate fi asociat cu orice element tinta;
poate fi sau nu poate fi mostenit de un element derivat;
instante multiple pot fi permise sau nu pe acelasi element tinta.
Aceste comportari sunt specificate in AttributeUsageAttribute.
Un atribut este o adnotare ce poate fi plasata pe un element al codului sursa si este folosit
pentru a memora in momentul compilarii, informatii specifice aplicatiei. Aceasta informatie
este memorata in metadata si poate fi accesata fie in timpul executiei aplicatiei, prin procesul
cunoscut sub numele de reflexie sau cand un alt utilitar citeste metadata. Atributele pot
schimba comportarea aplicatiei in momentul executiei.
CLI predefineste anumite tipuri de atribute si le foloseste pentru a controla comportarea la
runtime.
Putem crea propriile noastre clase de atribute, mostenite din Attribute. Definitia unei
asemenea clase include numele atributului, comportarea sa implicita si alte informatii.
Exemplu
Urmatorul exemplu creaza si atribuie atribute definite de utilizator unei anumite clase.
Atributul contine numele programatorului si versiunea clasei.
using System;
[AttributeUsage(AttributeTargets.Class|
AttributeTargets.Struct,
AllowMultiple=true)]
public class Author : Attribute
{
string authorName;
public double verSion;
public Author(string name)
{
authorName = name;
verSion = 1.0;
}
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
2
21.01.2007
[Author("Some Author"),
Author("Some Other Author", verSion=1.1)]
class ThirdClass
{
/*...*/
}
class AuthorInfo
{
public static void Main()
{
PrintAuthorInfo(typeof(FirstClass));
PrintAuthorInfo(typeof(SecondClass));
PrintAuthorInfo(typeof(ThirdClass));
}
public static void PrintAuthorInfo(Type type)
{
Console.WriteLine("Author information for {0}",
type);
Attribute[] attributeArray =
Attribute.GetCustomAttributes(type);
foreach(Attribute attrib in attributeArray)
{
if (attrib is Author)
{
Author author = (Author)attrib;
Console.WriteLine("
{0}, version {1:f}",
author.getName(),
author.verSion);
}
}
Console.WriteLine();
}
}
Iesirea este:
Author information for FirstClass
Some Author, version 1.00
Author information for SecondClass
Author information for ThirdClass
Some Author, version 1.00
Some Other Author, version 1.10
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
3
21.01.2007
Definirea atributelor
Un atribut este in momentul de fata o clasa derivata din System.Attribute.
Sintaxa folosita pentru a atasa un atribut la un tip sau membru este asemanatoare cu cea
folosita la instantierea unei clase.
Interogarea atributelor
Pentru a interoga un tip sau un membru despre atributele atasate acestuia, trebuie sa utilizam
reflexia (reflection).
Reflection ne permite de a determina in mod dinamic in momentul executiei caracteristicile
unei aplicatii.
Putem folosi reflection pentru a citi metadata pentru un intreg assembly si a produce o lista a
tuturor claselor, tipurilor si metodelor definite pentru acel assembly.
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
4
21.01.2007
*/
}
}
}
[RemoteObject(RemoteServers.COSETTE)]
class MyRemotableClass
{
}
Pentru a determina serverul pe care se creaza obiectul putem folosi urmatorul cod (explicatiile
sunt comentate in cod):
class Test
{
[STAThread]
static void Main(string[] args)
{
//
// Obtinem tipul obiectului asociat cu MyRemotableClass
//
Type type = typeof(MyRemotableClass);
//
// Dupa ce am obtinut obiectul, putem incepe interogarea lui
//
/*
GetCustomAttributes returneaza un vector ale carui elemente sunt
atributele obiectului. Parametrul true specifica daca cautarea
se face si pentru membrii mosteniti. Din cauza ca nu avem
mostenire in acest caz, putem folosi true/false cu acelasi
efect.
*/
foreach (Attribute attr in
type.GetCustomAttributes(true))
{
/*
Se incearca conversia atributului la
RemoteObjectAttribute.
Daca conversia nu reuseste atunci
remoteAttr = null;
*/
RemoteObjectAttribute remoteAttr =
attr as RemoteObjectAttribute;
if (null != remoteAttr)
{
Console.WriteLine(
"Create this object on {0}.",
remoteAttr.Server);
}
}
}
}
Rezultatul este:
Create this object on COSETTE.
Pentru a defini mai multe atribute la o clasa vezi si exemplul din pagina web.
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
5
21.01.2007
[AtributTranzactie]
public void Txt2()
{}
class Test
{
[STAThread]
static void Main(string[] args)
{
// Clasa se califica cu numele spatiului
// pentru ca am definit un namespace
Type type = Type.GetType("AtributeMetode.Atx");
foreach (MethodInfo method in type.GetMethods())
{
foreach (Attribute attr in
method.GetCustomAttributes(true))
{
if (attr is AtributTranzactie)
{
Console.WriteLine(
"Metoda
{0} are atributul AtributTranzactie.",
method.Name);
}
}
}
}
}
}
Iesirea este:
AtributTranzactie ctor
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
6
21.01.2007
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
7
21.01.2007
System;
System.IO;
System.Runtime.Serialization.Formatters.Soap;
System.Reflection;
System.Collections;
[Serializable]
public class User
{
[ValidLength(4,8,Message=
"UserID should be between 4 and 8 characters long")]
public string userID;
[ValidLength(4,8,Message=
"Password should be between 4 and 8 characters long")]
public string password;
[ValidLength(4,60)]
public string email;
public string city;
public void Save(string fileName)
{
FileStream s=new FileStream(fileName,FileMode.Create);
SoapFormatter sf=new SoapFormatter();
sf.Serialize(s,this);
}
static void Main(string[] args)
{
User u=new User();
u.userID="first";
u.password="Zxfd12Qs";
u.email=".com";
u.city="";
Validator v=new Validator();
if(!v.IsValid(u))
{
foreach(string message in v.Messages) Console.WriteLine(message); }
else {u.Save("user.txt");} }
}
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
8
21.01.2007
_min=min;
_max=max;
}
public string Message
{
get {return(_message);}
set {_message=value;}
}
public string Min
{
get{return _min.ToString();}
}
public string Max
{
get{return _max.ToString();}
}
public bool IsValid(string theValue)
{
int length=theValue.Length;
if(length >= _min && length <= _max) return true;
return false;
}
}
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
9
21.01.2007
Clasa Validator foloseste clasele reflection pentru a valida obiectul pasat ca parametru
metodei IsValid.
1. Se extrag toate campurile publice din obiect folosind metoda
GetType().GetFields(BindingFlags.Public|BindingFlags.Instance).
Pentru fiecare camp, se extrage atributul definit de utilizator de tip ValidLengthAttribute
folosind metoda GetCustomAttributes(typeof(ValidLengthAttribute),true).
Daca nu se gaseste atributul nostru pentru un camp, metoda presupune campul ca fiind valid.
Daca se gaseste atributul nostru pentru acel camp, se apeleaza metoda IsValid din
ValidLengthAttribute pentru a valida valoarea campului.
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
10
21.01.2007
Pentru a face FieldAttribute.Nume un parametru cu nume, il vom sterge din ctor pentru ca el
exista deja ca o proprietate read/write:
// public FieldAttribute(Informatica an, String nume)
public FieldAttribut(string nume)
{
// this.an = an;
this.nume = nume;
Console.WriteLine("Ctor FieldAttribute");
}
Utilizatorul poate atasa atributul in doua moduri:
[FieldAttribute("Popescu")]
public int nCuAtribut;
sau
[FieldAttribute(Popescu,An = Informatica.AN_4)]
public int nCuAtribut;
Cand folosim parametri cu nume, trebuie sa specificam parametri pozitionali mai intai, si apoi
parametri cu nume in orice ordine dorim.
Compilatorul incearca sa rezolve mai intai parametrii cu nume si apoi ce ramine, incearca sa
gaseasca un ctor cu signatura potrivita.
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
11
21.01.2007
Parametrii cu nume pot fi orice camp sau proprietate accesibila publica incluzind o
metoda setter care nu este statica sau constanta.
Tipurile parametrului attribut
Tipurile parametrilor pozitionali si ai celor cu nume pentru o clasa atribut sunt limitate la
tipurile parametrului atributului, si care poate fi:
bool, byte, char, double, float, int, long, short, string
System.Type
object
tipul enum cu conditia ca oriunde se gaseste definit sa fie accesibil in mod public.
un tablou unidimensional ce are ca tipuri de elemente unul din cele de mai sus.
Atributul AttributeUsage
AttributeUsage defineste modul cum atributele sunt folosite.
Sintaxa este:
[AttributeUsage(
validon,
AllowMultiple = allowmultiple,
Inherited = inherited
)]
Observam un parametru pozitional si doi cu nume.
Parametrul validon
Parametrul validon este de tipul AttributeTarget, ne permite sa specificam tipurile pe
care atributul poate fi atasat.
public enum AttributeTargets
{
Assembly
= 0x0001,
Module
= 0x0002,
Class
= 0x0004,
Struct
= 0x0008,
Enum
= 0x0010,
Constructor = 0x0020,
Method
= 0x0040,
Property
= 0x0080,
Field
= 0x0100,
Event
= 0x0200,
Interface
= 0x0400,
Parameter
= 0x0800,
Delegate
= 0x1000,
All = Assembly Module Class Struct Enum Constructor
Method Property Field Event Interface Parameter
Delegate,
ClassMembers = Class Struct Enum Constructor Method
Property Field Event Delegate Interface,
}
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
12
21.01.2007
Folosim acest parametru cand vrem sa controlam exact modul de utilizare al unui atribut. In
exemplelel anterioare am folosit atribute pentru clase, metode, campuri.
Pentru a fi siguri ca atributele pe care le-am scris sunt folosite pentru tipurile pentru care au
fost proiectate, putem indica in definitia atributului pentru ce este proiectat:
[AttributeUsage(AttributeTargets.Class)]
public class RemoteObjectAttribute : Attribute
{}
[AttributeUsage(AttributeTargets.Method)]
public class AtributTranzactie : Attribute
{}
[AttributeUsage(AttributeTargets.Field)]
public class FieldAttribute : Attribute
{}
[RemoteObject(RemoteServers.COSETTE)]
class SomeClass
{
[AtributTranzactie]
public void Foo() {}
[FieldAttribute("Bar", An = Informatica.AN_4)]
public int Bar;
Parametrul AllowMultiple
Ne permite sa definim un atribut ce poate fi folosit o singura data pentru un camp sau de mai
multe ori.
Implicit toate atributele sunt folosite ca single, deci nu putem declara de doua ori acelasi
atribut pentru un camp. Vezi exemplul:
public class SomethingAttribute : Attribute
{
public SomethingAttribute(String str){}
}
// Error: "Duplicate single-use Something attribute"
[Something("abc")]
[Something("def")]
class MyClass{}
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
13
21.01.2007
[AttributeUsage(AttributeTargets.All, AllowMultiple=true)]
public class SomethingAttribute : Attribute
{
public SomethingAttribute(String str){}
}
[Something("abc")]
[Something("def")]
class MyClass{}
Parametrul Inherited
Acest parametru ne spune daca atributul poate fi mostenit sau nu. Valoarea implicita este
false.
Parametrii AllowMultiple si Inherited trebuiesc considerati impreuna. Vezi tabelul de mai jos.
Inherited AllowMultiple Result
Atributul derivat suprascrie atributul
true
false
de baza.
Atributele derivate si cele din clasa de
true
true
baza sunt combinate.
De exemplu:
using System;
using System.Reflection;
namespace AttribInheritance
{
[AttributeUsage(
AttributeTargets.All,
//
AllowMultiple=true,
AllowMultiple=false,
Inherited=true
)]
public class SomethingAttribute : Attribute
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
public SomethingAttribute(string str)
{
this.name = str;
}
}
[Something("abc")]
class MyClass
{
}
[Something("def")]
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
14
21.01.2007
//
class Test
{
[STAThread]
static void Main(string[] args)
{
Type type =
Type.GetType("AttribInheritance.Another");
foreach (Attribute attr in
type.GetCustomAttributes(true))
type.GetCustomAttributes(false))
{
SomethingAttribute sa =
attr as SomethingAttribute;
if (null != sa)
{
Console.WriteLine(
"Custom Attribute: {0}",
sa.Name);
}
}
}
Identificatorii atributului
Trebuie sa precizam la ce se aplica un atribut: la o metoda sau la valoarea returnata de
metoda.
Din acest punct de vedere urmatorul cod este ambiguu.
class SomeClass
{
[HRESULT]
public long Foo() { return 0; }
}
In COM, HRESULT reprezinta valoarea returnata de metodele din interfata (mai putin
AddRef si Release, acestea returneaza ULONG).
Putem defini atributul HRESULT astfel:
public class HRESULTAttribute : Attribute
{
public HRESULTAttribute(){}
}
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
15
21.01.2007
Pentru a fixa lucrurile, putem folosi identificatorul atributului, listat mai jos:
assembly
module
type
method
property
event
field
param
return
Sintaxa este:
identificator:atribut
Atentie la :
Vezi si exemplul de mai jos.
class SomeClass
{
[HRESULT]
public long Foo() { return 0; }
[return: HRESULT]
public long Bar() { return 0; }
}
Alte exemple:
class SomeClass
{
[method: HRESULT]
public long Foo() { return 0; }
[return: HRESULT]
public long Bar() { return 0; }
[property: HRESULT]
public long Goo { get { return 12345; } }
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
16
21.01.2007
}
foreach (MemberInfo m in type.GetProperties())
{
foreach (Attribute a in
m.GetCustomAttributes(true))
{
Console.WriteLine(
"property: {0}, "
+ "CustomAttributes: {1}",
m.Name, a);
}
}
Rezultatul este:
method: Foo, CustomAttributes: AttribIdentifiers.HRESULTAttribute
method: Bar, ReturnTypeCustomAttribs:
AttribIdentifiers.HRESULTAttribute
property: Goo, CustomAttributes: AttribIdentifiers.HRESULTAttribute
Atribute predefinite
Cadrul de lucru .NET ofera clase de atribute predefinite, dintre care mai importante sunt:
Predefined .NET
Valid Targets
Attribute
AttributeUsage Class
CLSCompliant
Ioan Asiminoaei
All
Description
Specifies the valid usage of another attribute class.
Indicates whether a program element is compliant
with the Common Language Specification (CLS).
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
Predefined .NET
Valid Targets
Attribute
Conditional
Method
DllImport
Method
MTAThread
Method (Main)
NonSerialized
Field
Obsolete
ParamArray
Serializable
STAThread
StructLayout
ThreadStatic
17
21.01.2007
Description
Indicates that the compiler can ignore any calls to
this method if the associated string is defined.
Specifies the DLL location that contains the
implementation of an external method.
Indicates that the default threading model for an
application is multithreaded apartment (MTA).
Applies to fields of a class flagged as Serializable;
specifies that these fields wont be serialized.
All except
Marks an element obsoletein other words, it
Assembly, Module,
informs the user that the element will be removed
Parameter, and
in future versions of the product.
Return
Allows a single parameter to be implicitly treated
Parameter
as a params (array) parameter.
Class, struct, enum, Specifies that all public and private fields of this
delegate
type can be serialized.
Indicates that the default threading model for an
Method (Main)
application is STA.
Specifies the nature of the data layout of a class or
Class, struct
struct, such as Auto, Explicit, or Sequential.
Implements thread-local storage (TLS)in other
words, the given static field isnt shared across
Field (static)
multiple threads and each thread has its own copy
of the static field.
Atributul Conditional
Ideea: Apelul unei metode poate fi ignorat daca nu este definita o anumita valoare.
Exemplu:
[Conditional("DEBUG")]
public void SomeDebugFunc()
{ Console.WriteLine("SomeDebugFunc"); }
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
18
21.01.2007
Iesirea este:
SomeDebugFunc
SomeFunc
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
19
21.01.2007
Runtime .NET transmite parametrii din codul C# manged catre codul nativ din DLL.
Sintaxa completa pentru DllImport este:
[DllImport("user32", EntryPoint="MessageBoxA",
SetLastError=true,
CharSet=CharSet.Ansi, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern int MessageBoxA (
int h, string m, string c, int type);
Pentru a transmite structuri din codul managed catre codul unmanaged si invers trebuie sa
folosim atributul StructLayout, ce are ca efect construirea structurii exact ca in declaratia ei
initiala (adica secvential). Este obligatoriu acest lucru.
Exemplu pentru apelul functiei GetLocalTime().
[StructLayout(LayoutKind.Sequential)]
public class SystemTime {
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;
}
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
20
21.01.2007
Interfete
Interfetele ne dau posibilitatea de a defini o multime de metode si proprietati pe care clasa
selectata le poate implementa.
Din punct de vedere conceptual interfetele sunt contracte intre doua parti de cod separate.
Lucrurile stau in felul urmator:
se defineste o interfata (contine metode abstracte); interfata defineste o anumita
comportare ;
se defineste o clasa ce implementeaza aceasta interfata, se spune ca clasa este derivata
din interfata ;
clientii vor utiliza clasa ce a implementat interfata.
Utilizarea interfetei
In C#, o interfata este un concept de prima clasa, adica o trasatura preconstruita a
limbajului, ce declara un tip referinta ce include numai declaratiile metodelor.
Declararea interfetelor
Interfetele pot contine metode, proprietati, indexeri si evenimente, si nici unul nu este
implementat de interfata insasi. Interfetele sunt definte ca o clasa abstracta.
Exemple
interface IValidate
{
bool Validate();
}
Observatii
Nu trebuie sa declaram ca metodele sunt pur virtuale (=0).
interface IExempluInterface
{
// Exemplu de declarare a unei proprietati
int testProperty { get; }
// Exemplu de declarare a unui eveniment
event testEvent Changed;
Implementarea interfetelor
Fiecare clasa ce implementeaza o interfata trebuie sa defineasca fiecare membru al interfetei.
Sa examinam urmatorul exemplu.
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
21
21.01.2007
using System;
interface IValidate
{
bool Validate();
}
class InterfacesApp
{
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
22
21.01.2007
Operatorii is si as
Operatorul is test existenta interfata
Pentru a testa un obiect daca implementeaza o anumita interfata folosim operatorul is.
Operatorul is ne permite sa controlam in momentul executiei daca un tip este compatibil cu
alt tip. Sintaxa este:
expresie is ttip
Vezi exemplul ce urmeaza.
using System;
using System.Collections;
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
23
21.01.2007
interface IValidate
{
}
bool Validate();
// Test operator is
class IsOperatorApp
{
public static void Main()
{
// 1. Vom pune in acest ArrayList obiecte instantiate din SSN
// si Address.
// 2. Vom itera acest vector si pentru obiectele instantiate
// din SSN vom apela metoda Validate.
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
24
21.01.2007
Operatorul as
Operatorul as face conversia intre tipurile compatibile si are urmatoarea sintaxa:
obiect = expresie as tip
unde expresie este un tip referinta.
In urma acestei conversii trebuie scris cod de verificare a conversiei, adica daca obiect are o
valoare valida.
Exemplu
using System;
using System.Collections;
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
25
21.01.2007
interface IValidate
{
bool Validate();
return correctFormat;
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
26
21.01.2007
if (null != iValidate)
{
Console.WriteLine("\n\t{0} implementeaza IValidate",
control);
Console.Write("\t");
bool b = iValidate.Validate();
Console.WriteLine("\tValidare {0}",
(b == true ? "succeded" : "failed"));
}
else
{
Console.WriteLine("\n\t{0} nu " +
"implementeaza IValidate", control);
}
}
}
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
}
27
21.01.2007
class NameHiding2App
{
public static void Main()
{
Console.WriteLine();
EditBox edit = new EditBox();
Console.WriteLine("Calling EditBox.Bind()...");
// ERROR: This line won't compile because
// the Bind method no longer exists in the
// EditBox class's namespace.
edit.Bind();
Console.WriteLine();
Coliziuni de nume
Consideram urmatorul exemplu in care avem doua interfete ce contin o metoda cu acelasi
nume, SaveData, dar cu functionalitati diferite in cadrul fiecarei interfete.
using System;
interface ISerializable
{
void SaveData();
interface IDataStore
{
void SaveData();
}
}
class NameCollisions1App
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
{
28
21.01.2007
interface ISerializable
{
}
void SaveData();
interface IDataStore
{
void SaveData();
}
class NameCollisions2App
{
public static void Main()
{
Test test = new Test();
Console.WriteLine("Testing to see if Test " +
"implements ISerializable...");
Console.WriteLine("ISerializable is {0}implemented\n",
test is ISerializable ? "" : "NOT ");
Console.WriteLine("Testing to see if Test " +
"implements IDataStore...");
Console.WriteLine("IDataStore is {0}implemented\n",
test is IDataStore ? "" : "NOT ");
}
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
29
21.01.2007
Rezolvare problema
using System;
interface ISerializable
{
void SaveData();
interface IDataStore
{
void SaveData();
}
void IDataStore.SaveData()
{
Console.WriteLine("[Test.SaveData] IDataStore " +
"implementation called");
}
void ISerializable.SaveData()
{
}
}
class NameCollisions3App
{
public static void Main()
{
Test test = new Test();
Console.WriteLine("[Main] " +
"Testing to see if Test implements " +
"ISerializable...");
Console.WriteLine("[Main] " +
"ISerializable is {0}implemented",
test is ISerializable ? "" : "NOT ");
((ISerializable)test).SaveData();
Console.WriteLine();
Console.WriteLine("[Main] " +
Testing to see if Test implements " +
"IDataStore...");
Console.WriteLine("[Main] " +
"IDataStore is {0}implemented",
test is IDataStore ? "" : "NOT ");
((IDataStore)test).SaveData();
}
}
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
30
21.01.2007
Interfete si mostenirea
Cateva scenarii posibile
Exemplificare
using System;
class InterfaceInh1App
{
public static void Main()
{
EditBox edit = new EditBox();
edit.Serialize();
// Care metoda Serialize se executa?
}
}
Codul se compileaza desi nu am scris cod pentru Serialize din IDataBound. Daca codul
executa corect ceea ce am vrut noi este o alta problema.
In fapt se apelaeaza Serialize din clasa de baza.
Folosirea operatorului is nu rezolva problema neimplementarii unei metode din interfata.
Practic is spune ca o anumita clasa suporta o anumita interfata, dar nu ca o si
implementeaza.
Vezi exemplu:
using System;
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
31
21.01.2007
class InterfaceInh2App
{
interface ITest
{
}
void Foo();
Ioan Asiminoaei
Atribute si interfete
Facultatea de Informatica Iasi Universitatea Al I. Cuza Iasi
32
21.01.2007
new si casting-ul din ultima linie de cod rezolva problema in mod corect.
Se recomanda folosirea cast-ului in utilizarea metodelor din interfete.
Ioan Asiminoaei