I keep in mind the following concepts when designing with .NET Framework assemblies and types; that is, when doing object-oriented design —an activity also known as dependency management, which is equal and the same for the most part. Aggregation between two types occurs when Type B is the declared type of any member in the structure of Type A and the latter does not dispose the former’s instance; e.g. Type A aggregates Type B or Type A aggregates System.EventHandler: class A { private B b; public event System.EventHandler OnEvent; } Composition between two types occurs when Type B is the declared type of any member in the structure of Type A and the latter has the responsibility to dispose the former’s instance; e.g. Type A composes Type B: class A : System.IDisposable { private B b; public void Dispose() { b.Dispose(); } } Using between two types occurs when Type B is the declared type of any parameter in any method signature or local variable in method implementations of Type A; e.g. Type A is using Type B: class A { public B ItsBObject { get { return GetBObject(); } } public void ProcessB(B b) {} private B GetBObject() {} private void f() { B b=GetBObject(); } } Instantiation between two types occurs when Type B is instantiated by Type A; this relationship denotes the specific operation by of which Type A creates Type B instances; e.g. Type A instantiates Type B: class A { public void f() { B b=new B(); } }
class A { private B b; public event System.EventHandler OnEvent; }
class A : System.IDisposable { private B b; public void Dispose() { b.Dispose(); } }
class A { public B ItsBObject { get { return GetBObject(); } } public void ProcessB(B b) {} private B GetBObject() {} private void f() { B b=GetBObject(); } }
class A { public void f() { B b=new B(); } }