Sử dụng các lớp tĩnh làm không gian tên


21

Tôi đã thấy các nhà phát triển khác sử dụng các lớp tĩnh làm không gian tên

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

Để khởi tạo các lớp bên trong, nó sẽ trông như sau

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

Lý do là không gian tên có thể được ẩn bằng cách sử dụng từ khóa "bằng cách sử dụng". Nhưng bằng cách sử dụng các lớp tĩnh, các tên lớp lớp ngoài phải được chỉ định, giúp duy trì hiệu quả các không gian tên.

Microsoft khuyên chống lại điều đó trong hướng dẫn . Cá nhân tôi nghĩ rằng nó tác động đến khả năng đọc. Quan điểm của bạn là gì?


1
Tùy thuộc vào người triển khai cho dù họ cần các không gian tên có trong triển khai. Tại sao bạn buộc phải sử dụng các không gian tên (và các không gian tên giả ở đó) trên chúng?
Craige

Có thể cho mục đích nhóm? Giống như có rất nhiều lớp con và bằng cách nhóm các lớp con thành các lớp tĩnh. Điều đó làm cho cường độ rõ ràng?
dùng394128

Việc đặt các lớp con trong một không gian tên phụ cũng không làm cho ý định rõ ràng? Ngoài ra, đây là loại vấn đề được giải quyết bằng tài liệu.
Craige

Câu trả lời:


16

Sử dụng các lớp tĩnh làm không gian tên thách thức mục đích có không gian tên.

Sự khác biệt chính là ở đây:

Nếu bạn xác định CategoryA, CategoryB<là không gian tên và khi ứng dụng sử dụng hai không gian tên:

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

Ở đây nếu CategoryAhoặc CategoryBlà một lớp tĩnh chứ không phải là không gian tên, việc sử dụng cho ứng dụng gần giống như được mô tả ở trên.

Tuy nhiên, nếu bạn định nghĩa nó là một không gian tên và ứng dụng chỉ sử dụng 1 không gian tên (không bao gồm CategoryB), thì trong trường hợp đó, ứng dụng thực sự có thể sử dụng theo sau

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

Nhưng nếu bạn định nghĩa CategoryAlà một lớp tĩnh thì ở trên không xác định! Một người buộc phải viết CategoryA.somethingmỗi lần.

Không gian tên nên được sử dụng để tránh xung đột đặt tên trong khi phân cấp lớp nên được sử dụng khi nhóm lớp có một số liên quan đến mô hình hệ thống.


Ngoài ra, nếu ai đó muốn không sử dụng không gian tên, thậm chí sử dụng các lớp thì có thể: using Item1 = CategoryA.Item1(tôi nghĩ rằng nó hoạt động cho các lớp lồng nhau như đối với không gian tên)
George Duckett

1
Trong C ++, ADL không hoạt động với phạm vi lớp; nó hoạt động với phạm vi không gian tên. Vì vậy, trong C ++, không gian tên không chỉ là sự lựa chọn tự nhiên, nhưng đúngthành ngữ lựa chọn cũng .
Nawaz

Tôi nghĩ rằng đó là ý định của OP để tránh ẩn không gian tên bằng cách sử dụng từ khóa. Ông muốn buộc người dùng phải viết nó mỗi lần. Có lẽ không gian tên của anh ấy giống nhưvar s = new HideMe.MyPhoneNumberIs12345678.TheRealUsefulClass()
Gqqnbig 15/03/2017

5

Bất cứ điều gì đang xảy ra ở đây chắc chắn không phải là mã C # thành ngữ.

Có lẽ những người khác đang cố gắng triển khai mẫu mô-đun - điều này sẽ cho phép bạn có các hàm, hành động, v.v. cũng như các lớp trong 'không gian tên' (tức là lớp tĩnh trong trường hợp này)?


Tôi đồng ý, trông lạ.
marko

4

Trước hết, mỗi lớp nên ở trong một không gian tên, vì vậy ví dụ của bạn thực sự sẽ giống như:

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

Điều đó nói rằng, tôi thấy không có lợi ích của loại thể dục dụng cụ mã này khi bạn có thể xác định chính xác một không gian tên như vậy:

namespace SomeNamespace.CategoryA { ... }

Nếu bạn có thể một ngày nào đó nghĩ đến việc lưu trữ một số phương thức tĩnh ở cấp trên, điều này có thể có ý nghĩa, nhưng vẫn không phải là điều mà người tạo C # có trong tâm trí và có thể khiến người khác khó đọc hơn - tôi sẽ lãng phí rất nhiều thời gian suy nghĩ TẠI SAO bạn đã làm điều này và suy nghĩ nếu tôi thiếu một số tệp nguồn sẽ cung cấp giải thích.


Vậy tại sao enums là ngoại lệ của quy tắc ?
sq33G

Đó là một câu hỏi khác :) Nhưng tôi vẫn sẽ không định nghĩa một lớp tĩnh chỉ để định nghĩa các enum trong đó.
zmilojko

1

Các không gian tên trong Java, JavaScript và .NET không hoàn thành và chỉ cho phép lưu trữ các lớp, nhưng các thứ khác như hằng số hoặc phương thức toàn cầu thì không.

Nhiều nhà phát triển sử dụng thủ thuật "lớp tĩnh" hoặc "phương thức tĩnh", ngay cả khi một số người không khuyến nghị.


0

Tôi biết rằng đây là một câu hỏi cũ, nhưng một lý do rất hợp lệ để sử dụng một lớp làm không gian tên (không phải là tĩnh tại đó) là C # không hỗ trợ định nghĩa về không gian tên tham số hoặc chung. Tôi đã viết một bài đăng trên blog về chính chủ đề này ở đây: http://tyreejackson.com/generics-net-part5-generic-namespaces/ .

Ý chính của nó là, khi sử dụng khái quát để trừu tượng các chuỗi mã soạn sẵn, đôi khi cần phải chia sẻ nhiều tham số chung giữa các lớp và giao diện liên quan. Cách thông thường để làm điều này sẽ là xác định lại các tham số chung, các ràng buộc và tất cả trong mỗi giao diện và chữ ký lớp. Theo thời gian, điều này có thể dẫn đến sự phổ biến các tham số và các ràng buộc không đề cập đến việc liên tục phải đủ điều kiện các loại liên quan bằng cách chuyển tiếp các tham số loại từ một loại sang các đối số loại của loại liên quan.

Sử dụng một lớp Generic bên ngoài và lồng các kiểu liên quan bên trong có thể DRY mã lên một cách đáng kể và đơn giản hóa sự trừu tượng hóa của nó. Sau đó, người ta có thể rút ra lớp không gian tên tham số với một triển khai cụ thể cung cấp tất cả các chi tiết cụ thể.

Đây là một ví dụ tầm thường:

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

    }

}

Được sử dụng như thế này:

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

Tiêu thụ các dẫn xuất như thế này:

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

    }
}

Lợi ích của việc viết các kiểu theo cách này là thêm an toàn kiểu và ít hơn các kiểu trong các lớp trừu tượng. Nó tương đương ArrayListvới vs List<T>trên quy mô lớn hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.