Я знаю, що це давнє запитання, але однією з дуже вагомих причин використовувати клас як простір імен (нестатичний у цьому) є те, що C # не підтримує визначення параметричних чи загальних просторів імен. Я написав повідомлення в блозі на цю саму тему тут: http://tyreejackson.com/generics-net-part5-generic-namespaces/ .
Суть її полягає в тому, що при використанні дженерики для абстрагування величезних фрагментів кодового шаблону іноді доводиться ділити декілька загальних параметрів між пов'язаними класами та інтерфейсами. Умовному способі зробити це було б перевизначити загальні параметри, обмеження та все в кожному інтерфейсі та підписі класу. З часом це може призвести до поширення параметрів і обмежень, не кажучи вже про необхідність постійно кваліфікувати відповідні типи, пересилаючи параметри типу від одного типу до аргументів типу відповідного типу.
Використання зовнішнього загального класу та вкладення відповідних типів усередині може різко ЗУБИТИ код та спростити його абстрагування. Потім можна отримати параметричний клас простору імен з конкретною реалізацією, яка забезпечує всі конкретні деталі.
Ось тривіальний приклад:
public class Entity
<
TEntity,
TDataObject,
TDataObjectList,
TIBusiness,
TIDataAccess,
TIdKey
>
where TEntity : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>, subclassed
where TDataObject : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>.BaseDataObject, subclassed
where TDataObjectList : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>.BaseDataObjectList, subclassed
where TIBusiness : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>.IBaseBusiness
where TIDataAccess : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>.IBaseDataAccess
{
public class BaseDataObject
{
public TIdKey Id { get; set; }
}
public class BaseDataObjectList : Collection<TDataObject> {}
public interface IBaseBusiness
{
TDataObject LoadById(TIdKey id);
TDataObjectList LoadAll();
void Save(TDataObject item);
void Save(TDataObjectList items);
void DeleteById(TIdKey id);
bool Validate(TDataObject item);
bool Validate(TDataObjectList items);
}
public interface IBaseDataAccess
{
TDataObject LoadById(TIdKey id);
TDataObjectList LoadAll();
void Save(TDataObject item);
void Save(TDataObjectList items);
void DeleteById(TIdKey id);
}
}
Використовується так:
public class User
:
Entity
<
User,
User.DataObject,
User.DataObjectList,
User.IBusiness,
User.IDataAccess,
Guid
>
{
public class DataObject : BaseDataObject
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class DataObjectList : BaseDataObjectList {}
public interface IBusiness : IBaseBusiness
{
void DeactivateUserById(Guid id);
}
public interface IDataAcccess : IBaseDataAccess {}
}
Споживайте такі похідні:
public class EntityConsumer
{
private User.IBusiness userBusiness;
private Permission.IBusiness permissionBusiness;
public EntityConsumer(User.IBusiness userBusiness, Permission.IBusiness permissionBusiness) { /* assign dependencies */ }
public void ConsumeEntities()
{
var users = new User.DataObjectList();
var permissions = this.permissionBusiness.LoadAll();
users.Add
(new User.DataObject()
{
// Assign property values
});
this.userBusiness.Save(users);
}
}
Користь для написання типів таким чином додає безпеку типу та меншу кількість викидів у абстрактні класи. Його еквівалент ArrayList
vs List<T>
у більшому масштабі.