Statik sınıfları ad alanları olarak kullanma


21

Statik sınıfları ad alanları olarak kullanan diğer geliştiricileri gördüm.

public static class CategoryA
{
    public class Item1
    {
        public void DoSomething() { }
    }
    public class Item2
    {
        public void DoSomething() { }
    }
}

public static class CategoryB
{
    public class Item3
    {
        public void DoSomething() { }
    }
    public class Item4
    {
        public void DoSomething() { }
    }
}

İç sınıfları somutlaştırmak için, aşağıdaki gibi görünecektir.

CategoryA.Item1 item = new CategoryA.Item1();

Bunun mantığı, ad alanlarının "using" anahtar sözcüğü kullanılarak gizlenebilmesidir. Ancak statik sınıfları kullanarak, ad alanlarını etkin bir şekilde koruyan dış katman sınıf adlarının belirtilmesi gerekir.

Microsoft , kılavuzda buna karşı tavsiyelerde bulunur . Şahsen okunabilirliği etkilediğini düşünüyorum. Düşüncelerin nelerdir?


1
Uygulamada yer alan ad alanlarına ihtiyaç duyup duymadıkları uygulayıcıya bağlıdır. Neden bunlara isim alanları (ve bu konuda sahte isim alanları) kullanımını zorladınız?
Craige

Gruplama amacıyla olabilir mi? Gibi birçok alt sınıflar vardır ve alt sınıfları statik sınıflara gruplayarak. Bu niyeti netleştiriyor mu?
user394128 10:11

Alt sınıfları bir alt ad alanına koymak da niyeti netleştirmez mi? Ayrıca, bu dokümantasyonla çözülen problem türüdür.
Craige

Yanıtlar:


16

Statik sınıfları ad alanları olarak kullanmak, ad alanlarına sahip olmanın amacını belirler.

Anahtar fark burada:

Eğer tanımlarsanız CategoryA, CategoryB<ad olarak ve uygulama iki ad kullandığında:

CategoryA::Item1 item = new CategoryA::Item1(); 
CategoryB::Item1 item = new CategoryB::Item1();

Burada CategoryAveya CategoryB, ad alanı yerine statik bir sınıfsa, uygulamanın kullanımı yukarıda açıklandığı şekilde neredeyse aynıdır.

Ancak, onu bir ad alanı olarak tanımlarsanız ve uygulama yalnızca 1 ad alanı kullanır (içermez CategoryB), bu durumda uygulama aslında aşağıdakileri kullanabilir

using namespace CategoryA; 
Item1 item = new Item1(); 

Fakat CategoryAstatik bir sınıf olarak tanımlasaydınız yukarıdaki tanımsızdı! Biri CategoryA.somethingher seferinde yazmak zorunda kalır .

Ad boşluklarını adlandırmaktan kaçınmak için ad alanları kullanılmalıdır; oysa sınıf gruplandırması sistem modeliyle bir ilgisi olduğunda sınıf hiyerarşisi kullanılmalıdır.


Ayrıca, birisi ad alanları kullanmak istemiyorsa, sınıfları bile kullanabiliyorsa: using Item1 = CategoryA.Item1(iç mekan sınıfları için ad alanları için çalıştığını düşünüyorum)
George Duckett

1
C ++ 'da ADL sınıf kapsamı ile çalışmaz; ad alanı kapsamı ile çalışır. Dolayısıyla, C ++ 'da ad alanı sadece doğal bir seçim değil, aynı zamanda doğru ve deyimsel bir seçimdir .
Nawaz

Bence OP’in, kullanarak anahtar sözcüğü kullanarak ad alanını gizlemekten kaçınmak istediğini düşünüyorum. Kullanıcıları her zaman yazmaya zorlamak istiyor. Belki de onun alanı gibidirvar s = new HideMe.MyPhoneNumberIs12345678.TheRealUsefulClass()
Gqqnbig

5

Burada olan her şey kesinlikle aptalca C # kodu değil.

Belki bu diğerleri modül modelini uygulamaya çalışıyorlar - bu size 'isim alanındaki' sınıfların yanı sıra işlevler, eylemler ve benzerleri de sağlar (yani bu durumda statik sınıf)?


Katılıyorum, garip görünüyor.
marko

4

Her şeyden önce, her sınıfın bir ad alanında olması gerekir, bu nedenle örneğiniz aslında şöyle olacaktır:

SomeNamespace.CategoryA.Item1 item = new SomeNamespace.CategoryA.Item1();

Bununla birlikte, böyle bir ad alanını tanımlayabildiğiniz zaman, bu tür bir kod jimnastiğinden fayda göremiyorum:

namespace SomeNamespace.CategoryA { ... }

Bazı günler bazı statik yöntemleri üst sınıf düzeyinde saklamayı düşünürseniz, bu mantıklı olabilir, ama yine de C # yaratıcılarının aklında olan şey değildir ve bunu başkalarına daha az okunabilir hale getirebilir - çok fazla zaman harcardım Bunu NEDEN yaptığınızı ve açıklama yapacak bazı kaynak dosyalarının eksik olup olmadığını düşünüyorum.


Öyleyse neden kuralın istisnası sayılıyor ?
sq33G

Bu farklı bir sorudur :) Ama yine de sadece içindeki sözcükleri tanımlamak için statik bir sınıf tanımlamam.
zmilojko

1

Java, JavaScript ve .NET ile ilgili ad alanları tamamlanmadı ve yalnızca sınıfları saklamalarına izin veriyor, ancak sabitler veya genel yöntemler gibi diğer şeyler yapmıyor.

Birçok geliştirici, bazılarına tavsiye edilmese bile "statik sınıflar" veya "statik yöntemler" püf noktalarını kullanır.


0

Bunun eski bir soru olduğunu biliyorum, ancak bir sınıfı ad alanı olarak kullanmanın çok geçerli bir nedeni (statik olmayan bir tane) C # parametrik veya genel ad alanlarının tanımını desteklemiyor. Bu konuyla ilgili bir blog yazısı buraya yazdım : http://tyreejackson.com/generics-net-part5-generic-namespaces/ .

Bunun temel amacı, büyük kazan plakası kodlarını tasarlamak için jenerik kullanırken, bazen ilgili sınıflar ve arayüzler arasında çoklu jenerik parametreleri paylaşmak gerekir. Bunu yapmanın geleneksel yolu, genel parametreleri, kısıtlamaları ve her bir arayüzdeki ve sınıf imzasındaki tüm parametreleri yeniden tanımlamak olacaktır. Zamanla bu, tür parametrelerini bir türden ilgili türün tür argümanlarına ileterek, ilgili türlerin sürekli olarak nitelendirilmesi gerekmediğinden, parametrelerin ve kısıtlamaların çoğalmasına neden olabilir.

Dış bir Genel sınıf kullanmak ve ilgili türlerin içine yerleştirmek, kodu önemli ölçüde KURUTABİLİR ve soyutlamasını basitleştirir. Daha sonra, parametrik ad alanı sınıfını, tüm somut ayrıntıları sağlayan somut bir uygulama ile türetebilirsiniz.

İşte önemsiz bir örnek:

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);

    }

}

Bu gibi kullanılır:

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 {}
}

Bunun gibi türevleri tüketin:

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);

    }
}

Türleri bu şekilde yazmanın faydası, sınıf güvenliği ve soyut sınıflarda türlerin daha az kullanılmasıdır. Onun daha büyük bir ölçekte ArrayListvs eşdeğeri List<T>.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.