Posts Tagged ‘Interfejsy’

Z cyklu ważne interfejsy .NET – ICloneable

wtorek, Marzec 16th, 2010

Na łamach bloga chciałbym abyśmy zrobili sobie małą powtórkę. Zapewne dla niektórych będą to też duże nowości. Niemniej znajomość interfejsów, które postaram się tu przytoczyć jest na tyle ważna, że każdy post zwróci się z nawiązką zarówno jednej jak i drugiej grupie osób:)

Otóż w bibliotece .NET znajduje się wiele interfejsów godnych uwagi. Twórcy z Microsoftu umieścili nawet część z nich w przestrzeni nazw „System”. Jednym (i zarazem jednym z najprostszych) z nich jest interfejs System.ICloneable, którego zadaniem jest utrzymywanie kontroli nad sposobem tworzenia kopii elementów. Interfejs posiada bowiem jedną metodę o nazwie Clone(), używaną do tworzenia kopii tego elementu:

public interface ICloneable
{
   object Clone();
}

Istnieją dwa sposoby implementacji interfejsu: tzw. głęboka kopia (deep-copy) i płytka kopia (shallow copy). Głęboka kopia polega na kopiowaniu danego obiektu i wszystkich obiektów, do których dana instancja się odnosi (przechodząc rekurencyjnie do wszystkich osiągalnych). Płytka kopia polega na kopiowaniu jedynie wybranych danych, najczęściej tych na najwyższym poziomie (choć nie musi realizować niczego, tak jak może realizować jedynie część głębokiej kopii). Należy zwrócić na to szczególną uwagę, gdyż z powodu tej różnicy różne klasy mogą mieć różne jej implementacje i nie możemy z góry polegać na realizacji jednej z nich. Standardowo, w celu stworzenia płytkiej kopii wystarczy zastosować bowiem metodę MemberwiseClone (dostępną dla każdego obiektu): System.Object.MemberwiseClone. Kopia taka nie radzi sobie jednak z typami referencyjnymi zagnieżdżonymi w klonowanym obiekcie – potrafi poprawnie kopiować tylko tzw. Value Types.

Przykład zastosowania:

using System;
class MyClass :ICloneable
{
   public int myField;
   public MyClass()
   {
      myField = 0;
   }
   public MyClass(int value)
   {
      myField = value;
   }
   public object Clone()
   {
      return this.MemberwiseClone();
   }
}

public class TestMyClass
{
   public static void Main()
   {
      MyClass my1 = new MyClass(44);
      MyClass my2 = (MyClass) my1.Clone();
      Console.WriteLine("my1 {0} my2 {1}",my1.myField, my2.myField);
      my2.myField = 22;
      Console.WriteLine("my1 {0} my2 {1}",my1.myField, my2.myField);
   }
}

wyświetli nam odpowiednio:
my1 44 my2 44
my1 44 my2 22

…a przykład zaczerpnięty został przeze mnie stąd: http://www.gnu.org/projects/dotgnu/pnetlib-doc/System/ICloneable.html.

…już wkrótce o IDisposable:)