2010-02-08 23 views
39

Một đồng nghiệp vừa tạo cấu trúc sau trong C# (mã ví dụ được đơn giản hóa). Mục tiêu của ông là rút ngắn ký hiệu cho tất cả các chuỗi được xác định trước trong phần còn lại của mã.C# Lớp tĩnh so với cấu trúc cho chuỗi được xác định trước

public struct PredefinedStrings 
{ 
    public const string VeryLongName = "Very Long Name"; 
    public const string AnotherVeryLongName = "Another Very Long Name"; 
    public const string TheLastVeryLongName = "The Last Very Long Name"; 
} 

public static void MethodThatUsesTheNames() 
{ 
    Console.WriteLine(PredefinedStrings.VeryLongName); 
    Console.WriteLine(PredefinedStrings.AnotherVeryLongName); 
    Console.WriteLine(PredefinedStrings.TheLastVeryLongName); 
} 

Mặc dù nó có vẻ làm việc tốt cho anh ta, tôi không thể ngừng tự hỏi liệu anh ta nên đã sử dụng một lớp tĩnh thay vì một struct hoặc nếu có một cách thanh lịch hơn để đạt được điều này.

Cách ưa thích để làm điều này là gì? Cũng vui lòng giải thích lý do.

+5

Kudo với đồng nghiệp của bạn! Đồng nghiệp của tôi hiếm khi sử dụng các const và chúng tôi có các chuỗi ký tự xâu chuỗi rải rác khắp mã của chúng tôi! lol Tôi nghĩ rằng, mặc dù, lớp tĩnh là loại tiêu chuẩn. –

+0

Tôi cũng đang nghĩ đến việc làm điều này nhưng cảm thấy tôi đang quá kỹ thuật. Tôi thường có một cuộc đình công 2/3 và cách tiếp cận refactor trong đó tôi scatter chuỗi literals ban đầu sau đó một khi tôi cần cùng một chuỗi một lần nữa trong một phương pháp hoặc lớp sau đó tôi sẽ giải nén nó vào một lớp tĩnh.Nó có thể là một chút tẻ nhạt mặc dù. – ozzy432836

Trả lời

34

Với giải pháp struct, không có gì là để ngăn chặn một số mã khác làm new PredefinedStrings(), mà sẽ không làm bất cứ điều gì xấu, nhưng là một cái gì đó thật khó hiểu ngữ nghĩa cho phép. Với một lớp tĩnh trình biên dịch sẽ cấm tạo cho bạn. Và nó đi mà không nói rằng lớp tĩnh là cách ưa thích của việc cung cấp các hằng số trong Framework.

chỉnh sửa thêm, tôi đã nói rằng phần thứ hai mà không cần bằng chứng - Tôi đã từ tìm kiếm và hợp lý nhanh chóng tìm thấy System.Net.Mime.DispositionTypeNamesSystem.Net.WebRequestMethods.Http.

+0

Đó có thể là lý do tại sao việc sử dụng cấu trúc khiến tôi cau mày lúc đầu, nhưng tôi đã không 't nghĩ về việc kiểm tra' quy ước '. Cảm ơn cho những người đứng đầu lên. Câu trả lời này rất hữu ích cho việc lựa chọn giữa cấu trúc và lớp tĩnh và có thể sẽ đủ để thực hiện công việc. Tuy nhiên tôi sẽ phải kiểm tra xem việc sử dụng các tập tin tài nguyên có thể phù hợp ở đây không. –

+0

Tôi chấp nhận câu trả lời này vì câu trả lời có vẻ phù hợp với tình huống cụ thể này, vì rất hiếm khi các chuỗi sẽ thay đổi. Sử dụng các tập tin tài nguyên là thú vị nhưng thêm quá nhiều phức tạp cho mã hiện tại vào lúc này. –

0

Trong thực tế của tôi cho mục đích này, chúng tôi sử dụng Dictionary<enumNameType, string>. Trường hợp enumNameType là loại tên khác nhau bạn có thể có (trong trường hợp của bạn) ... Từ điển này được bọc trong một lớp tĩnh và được lưu trữ - chúng ta tạo nó chỉ lần đầu tiên chúng ta sử dụng nó và sau đó trả về cùng một đối tượng ...

Tôi hy vọng điều này cũng hữu ích cho bạn!

+0

Lợi ích của việc này khi sử dụng các giá trị không đổi là gì? Với từ điển bạn có thể tra cứu nhanh, có, nhưng không nhanh như tham chiếu một giá trị không đổi trực tiếp. –

+0

@Dan Lợi ích là chúng ta sử dụng lại danh pháp trong loại enum. Chúng ta có thể sử dụng ở khắp mọi nơi ngữ nghĩa cần nó và loại enum này đại diện cho một danh pháp được liên kết với một danh pháp người dùng thân thiện trong từ điển. – anthares

+0

Có vẻ như bạn đang nói về việc có một cách hiệu quả để lấy một chuỗi từ một enum * mà bạn đang thực sự sử dụng như một enum *. Tôi có ấn tượng rằng OP quan tâm nhiều hơn đến các trường hợp bạn chỉ quan tâm đến một giá trị chuỗi không đổi; nhưng tôi có thể sai. –

5

Không có lỗi chức năng nào với mã này. Nhưng về mặt phong cách, tôi đồng ý một lớp tĩnh là tốt hơn. Một lớp tĩnh tuyên bố ý định của kiểu là chỉ giữ dữ liệu tĩnh/hằng số.

27

Tôi muốn các chuỗi tất cả nằm trong tệp tài nguyên và không được nhúng trong mã - chủ yếu vì lý do quốc tế hóa. Điều này sau đó có thể được truy cập thông qua một lớp tĩnh với các giá trị như các thành viên tài sản.

+2

+1, đây là câu trả lời. Và không chỉ cho quốc tế hóa, mà còn sử dụng tệp tài nguyên cho phép bạn sửa lỗi hoặc cập nhật chuỗi của bạn mà không cần phải xây dựng lại toàn bộ ứng dụng. –

+3

Funny Tôi đã nói điều tương tự sớm hơn câu trả lời này .. upvotes của tôi ở đâu ?? : P –

+3

Trong trường hợp này, chúng tôi khá chắc chắn các chuỗi sẽ không thay đổi, sử dụng các tệp tài nguyên có vẻ là một chút quá mức cần thiết cho tình huống cụ thể này. Một lớp tĩnh sẽ thực hiện công việc (hiện tại). Tuy nhiên tôi sẽ ghi nhớ điều này để sử dụng trong tương lai. Cảm ơn! –

22

Bên cạnh static classstruct, tại sao bạn không cân nhắc sử dụng các tệp resource cho các chuỗi không đổi? Đây có thể được truy cập rất dễ dàng như SomeNamespace.ResourceName.KeyName, và tùy thuộc vào nơi chúng được đặt trong dự án của bạn có thể được quản lý bên ngoài mà không cần biên dịch lại ...

+1

Kiểm tra dấu thời gian và bạn đã 1 phút sau, nhưng tôi sẽ cung cấp cho bạn +1 :) – Andrew

+1

Cảm ơn LOL. Tôi upvoted của bạn trước đó ... –

1

Tôi nghĩ tĩnh là tốt hơn và đây là lý do của tôi. Nếu mã này sống trong một số thư viện, và một đoạn mã khác tiêu thụ thư viện này, nếu giá trị của các trường liên tục thay đổi, thì không chỉ thư viện này cần được biên dịch lại (duh) mà còn phải biên dịch lại mã này thư viện là tốt. Lý do cho điều đó là, biên dịch chèn các giá trị không đổi bất cứ nơi nào bạn tham khảo chúng. Nếu bạn sử dụng tĩnh mặc dù, bạn sẽ không gặp phải vấn đề này, vì bạn đang tham chiếu đến trường không phải là giá trị .

0

Tôi cũng sử dụng cấu trúc cho các hằng số nhưng chỉ sử dụng cho mục đích sử dụng nội bộ, không dành cho API công khai. Nó cảm thấy tự nhiên vì enums cũng được chuyển đổi thành cấu trúc.

5

Có vẻ như bạn đang tìm kiếm tệp tài nguyên (.resx). Đó là một nơi thích hợp để lưu trữ các chuỗi như vậy và trừu tượng chuỗi của bạn thành một .resx sẽ giúp dễ dàng bản địa hóa ứng dụng của bạn trong tương lai. Trang MSDN tại http://msdn.microsoft.com/en-us/library/1ztca10y.aspx là một khởi đầu tốt để biết thêm thông tin.

5

Đừng quên đề xuất rằng kích thước cấu trúc phải là khoảng 16 byte. Với hệ thống 32 bit, đó là 4 tham chiếu System.String ngay tại đó. Tôi muốn nói rằng bạn tốt hơn với một lớp tĩnh nếu số lượng chuỗi sẽ tăng lên.

+0

Điểm tốt. Tôi nhớ đã đọc nó trước đó, nhưng đã không đặt nó trong thực tế trong một thời gian dài, vì hầu hết mã của tôi dường như không phù hợp cho cấu trúc :-) –

9

Quy tắc chung: không bao giờ sử dụng cấu trúc cho đến khi bạn không còn lựa chọn nào khác.

Constants có một vài nhược điểm:

  • loại chỉ đơn giản có thể được sử dụng (chuỗi, numerics, vv)
  • hằng được tiêm vào hội tham khảo. Nếu bạn biên dịch lại lắp ráp với các hằng số và không biên dịch assembly có sử dụng các hằng số, bạn sẽ gặp rắc rối

tôi sẽ viết mã của bạn như thế này (thông báo đổi tên refactoring quá):

public static class KnownNames 
{ 
    public static readonly string VeryLong = "Very Long Name"; 
    public static readonly string AnotherVeryLong = "Another Very Long Name"; 
    public static readonly string TheLastVeryLong = "The Last Very Long Name"; 
} 
+2

Hãy cẩn thận để giải thích tại sao bạn sử dụng 'chỉ đọc tĩnh' thay vì const? Const sẽ được đánh giá biên dịch-thời gian, đó là tốt cho việc sử dụng dự định. –

+2

Tôi đã liệt kê các nhược điểm của const: các loại đơn giản và các giá trị được biên dịch. Sử dụng const nếu bạn chắc chắn 100% nó sẽ không thay đổi (ví dụ như Math.Pi) –

+1

Tôi nhận được quan điểm của bạn, cảm ơn vì đã xây dựng. Tôi không mong đợi các giá trị thay đổi, nhưng bạn không bao giờ biết ai quyết định thay đổi các giá trị trong trí tuệ vô tận của mình ;-) –

1

tĩnh lớp học có vẻ là cách tốt nhất để đi vì đó là tiêu chuẩn nhất và được mong đợi. Tôi nghĩ rằng các phiên bản struct/const có thể nhanh hơn nhưng sau một số thử nghiệm thì không.

Dưới đây là kết quả thử nghiệm nhanh của tôi bao gồm chiều dài, so sánh, concat, sao chép, indexOf và chuỗi con. Nó được chạy dưới .Net 4.0 trong bản phát hành mà không có trình gỡ rối đính kèm.

          .Net 3.0 .Net 4.0 
static class with static read-only string: 0.217 0.364 seconds 
static class with const   string: 0.211 0.361 seconds 
struct  with static read-only string: 0.211 0.372 seconds 
struct  with const   string: 0.214 0.371 seconds 
Properties.Resources    string: 1.173 1.268 seconds 

Tất cả đều có cùng hiệu suất ngoại trừ khi sử dụng tệp tài nguyên chậm hơn. Trong khi Properties.Resources chậm hơn, nó không được lưu trữ trong tệp thực thi để có thể phù hợp hơn trong một số trường hợp. Vì vậy, sử dụng hoặc là "lớp tĩnh" hoặc Properties.Resources lưu trữ các chuỗi theo ý kiến ​​của tôi.

1

Thường tránh sử dụng các đường ống trừ khi chúng đáp ứng các tiêu chí nhất định như được nêu chi tiết trong this answer.

Vì đồng nghiệp của bạn không sử dụng nó để lưu trữ một giá trị, nên sử dụng một lớp, không phải là cấu trúc.

0

Thực tế đơn giản là bạn được phép tạo đối tượng mới được dự định là hằng số là bằng chứng rõ ràng về thực hành không tốt (thường). Tôi nói "thường" bởi vì .NET không sử dụng khái niệm này đôi khi, mặc dù nó không rõ ràng tại sao.

Tất nhiên, bạn luôn có thể làm những thứ như thế này:

public class Foo 
{ 
    public struct Bar 
    { 
     public static double A = 100; 

     public Bar(double a) 
     { 
      A = a; 
     } 
    } 
} 

Mà không kỹ thuật biện minh cho việc tạo ra các Bar; tuy nhiên, không có gì đảm bảo rằng hằng số Bar sẽ không thay đổi (ngay cả trong môi trường một luồng) và cuối cùng là sử dụng ít.

Các vấn đề liên quan