By Juval Löwy
Book Price: $44.95 USD
£31.95 GBP
PDF Price: $35.99
Cover | Table of Contents
public class MyClass
{
public string GetMessage()
{
return "Hello";
}
}
interface defines a CLR reference type that can't have any implementation, can't be instantiated, and has only public members. Saying that an interface can't have implementation means that it's as if all the interface's methods and properties were abstract. Saying it can't be instantiated means the same as if the interface were an abstract class (or MustInherit in Visual Basic 2005). For example, this interface definition:
public interface IMyInterface
{
void Method1();
void Method2();
void Method3();
}
public abstract class MyInterface
{
public abstract void Method1();
public abstract void Method2();
public abstract void Method3();
}
interface defines a CLR reference type that can't have any implementation, can't be instantiated, and has only public members. Saying that an interface can't have implementation means that it's as if all the interface's methods and properties were abstract. Saying it can't be instantiated means the same as if the interface were an abstract class (or MustInherit in Visual Basic 2005). For example, this interface definition:
public interface IMyInterface
{
void Method1();
void Method2();
void Method3();
}
public abstract class MyInterface
{
public abstract void Method1();
public abstract void Method2();
public abstract void Method3();
}
I and capitalize the first letter of the domain term, as in IAccount, IController, ICalculator, and so on. Use the I prefix even if the domain term itself starts with an I (such as in IIDentity or IImage). .NET tries to do away with the old Windows and C++ Hungarian naming notations (that is, prefixing a variable name with its type), but the I prefix is a direct legacy from COM, and that tradition is maintained in .NET.
IMyInterface obj;
obj = new MyClass();
obj.Method1();
MyClass doesn't implement the IMyInterface interface, the compiler refuses to generate the code and produces a compilation error. The compiler can do that because it can read the class's metadata and can tell in advance that the class doesn't derive from the interface. However, there are a number of cases where you cannot use implicit casting. In such cases, you can use explicit cast instead. Explicit casting means casting one type to another type:IList<T> interface:
public interface IList<T>
{
void AddHead(T item);
void RemoveHead(T item);
void RemoveAll();
}
public class NumberList : IList<int>
{
public void AddHead(int item)
{...}
public void RemoveHead(int item)
{...}
public void RemoveAll()
{...}
//Rest of the implementation
}
IList<T>, it must choose an implementation of the interface with a specific type parameter:
IList<int> list = new NumberList();
list.AddHead(3);
public class NumberList : IList<int>
{...}
public class NameList : IList<string>
{...}
IList<int> cannot be assigned to a variable or passed to a method that expects an IList<string>:
void ProcessList(IList<strin; names)
{...}
IList<int> numbers = new NumberList();
ProcessList(numbers);//Does not compile
IDog interface and have different kinds of dogs, such as Poodle and GermanShepherd, implement the IDog interface:
public interface IDog
{
void Fetch();
void Bark();
long VetClinicNumber{get;set;}
bool HasShots{get;set;}
}
public class Poo: IDog
{...}
public class GermanShepherd : IDog
{...}
IDog interface isn't well-factored. Even though all the interface members are things a dog should support, Exception and do not contain any other code. A skeletal implementation is required to at least get the code compiled as a starting point for your implementation of an interface, and it prevents clients from consuming a half-baked implementation. To have Visual Studio 2005 generate a skeletal interface implementation, you first add the interface to the class derivation chain. When you finish typing the interface name (such as IMyInterface), Visual Studio 2005 marks a little underscore tag under the I of the interface name. If you hover over IMyInterface, Visual Studio 2005 pops up a smart tag with a tool tip, "Options to implement interface." If you click the down arrow of the smart tip you can select from two options in the menu, implementing the interface either implicitly or explicitly (see Figure 3-2).
#region directive. For example, consider this interface definition:
public interface IMyInterface
{
void Method1();
int Method2(int number);
string Method3();
}
public class MyClass : IMyInterface
{
#region IMyInterface Members
void IMyInterface.Method1()
{
throw new Exception();
}
int IMyInterface.Method2(int number)
{
throw new Exception();
}
string IMyInterface.Method3()
{
throw new Exception();
}
#endregion
}
new operator on a class:
MyClass obj = new MyClass();
new operator on a class:
MyClass obj = new MyClass();
{//beginning of a C++ scope
MyClass object;
//use object;
}//end of scope, C++ calls the object destructor
delete operator is used:
//in C++:
MyClass* pObject = new MyClass;
//using pObject, then de-allocating it
delete pObject;
AddRef() to increment the counter. New COM objects are created with a reference count of one. When a client is done with an object, it calls Release() to decrement the counter:
//COM pseudo-code:
IMyInterface* pObject = NULL;
::CoCreateInstance(CLSID_MyClass,IID_IMyInterface,&pObject);
//using pObject, then releasing it
pObject->Release();
//COM implementation of IUnknown::Release()
ULONG MyClass::Release()
{
//m_Counter is this class counter
m_Counter--;
if(m_Counter == 0)
{
delete this;
return 0;
}
//Should return the counter:
return m_Counter;
}
Main, for example), but also internal .NET entities that should be kept alive as long as the application is running. Each root forms the topmost node in a tree-like graph. .NET keeps track of each new object it allocates off the managed heap and of the relationship between this object and its clients. Whenever an object is allocated, .NET updates its graph of objects and adds a reference in the graph to that object from the object that created it. Similarly, .NET updates the graph every time a client receives a reference to an object and when an object saves a reference to another object as a member variable. The JIT compiler also injects code to update the graphs each time the execution path enters or exits a scope.Finalize(), defined as:
protected void Finalize();
Finalize() method, the garbage collector doesn't destroy the object. Instead, the garbage collector marks the object as reachable (so it will not be overwritten by heap compaction), then moves the object from its original graph to a special queue called the finalization queue
. This queue is essentially just another object graph, and the root of the queue keeps the object reachable. The garbage collector then proceeds with collecting the garbage and compacting the heap. Meanwhile, a separate thread iterates over all the objects in the finalization queue, calling the Finalize() method on each and letting the objects do their cleanup. After calling Finalize(), the garbage collector removes the object from the queue.Collect() of the GC class, defined in the System namespace:
public static class GC
{
public static void Collect();
/* Other methods and members */
}
Finalize() (or the C# destructor) is called. This is done at an undetermined point in the future, usually when certain memory-exhaustion thresholds are met. In theory, releasing the expensive resources the object holds may never happen, thus severely hampering system scalability and throughput.Open() and Close().Close() on the object, allowing the object to release the file. If the client wants to access the file again, it calls Open(), without re-creating the object. The classic example of classes that implement this pattern are the database connection classes.Close() is that it makes sharing the object between clients a lot more complex than COM's reference counting. The clients have to coordinate which one is responsible for calling
AssemblyVersion. For example, the AssemblyVersion value corresponding to the settings in is:
[assembly: AssemblyVersion("1.2.3.4")]
MyClass from version 1.2.3.4 of the assembly MyAssembly, the manifest of the client will record that the client requires version 1.2.3.4 of MyAssembly to operate and will contain this declaration:
.assembly extern MyAssembly
{
.ver 1:2:3:4
}