2011-04-25 14 views
12

Tôi chưa bao giờ đăng một câu hỏi về bản chất này trước đây, vì vậy nếu nó không thích hợp cho SO, chỉ cần không làm tổn thương cảm xúc của tôi quá xấu và tôi sẽ xóa nó.Có C# spec (nhóm? Ủy ban?) Bao giờ được coi là cú pháp tạo đối tượng này?

Vì lợi ích của việc giữ tất cả mọi thứ tôi quan tâm đến càng gần lề trái càng tốt, tôi tiếp tục có nhu cầu tôi có thể viết một cái gì đó như:

DataService1.DataEntities dataEntities = new(constructorArg1, ...) 

Tôi nghĩ rằng một lý do khác là tôi thích màn hình thêm thực bất động sản tôi nhận được bằng cách sử dụng var khi các loại đã có mặt ở phía bên phải của nhiệm vụ, nhưng bộ não của tôi có quá nhiều năm tìm kiếm các loại ở phía bên trái. Sau đó, một lần nữa, bị mắc kẹt theo cách của tôi không phải là một lý do tốt để mong muốn một thông số kỹ thuật ...

+2

Hmm, điều này thật thú vị, +1. Tôi cũng vậy, như nó tốt hơn so với tùy chọn 'var' bởi vì nó nhận được thông tin kiểu ở bên trái nơi nó thuộc về. (Bây giờ có được ra bãi cỏ của tôi!) –

+18

Tôi lưu ý rằng câu hỏi có phiếu bầu để đóng dựa trên "chủ quan và tranh luận". Câu hỏi không chủ quan cũng không tranh luận; câu hỏi là một câu hỏi thực tế đơn giản về việc liệu một tính năng cụ thể có đưa ra thảo luận trong cuộc họp thiết kế ngôn ngữ hay không; đó là câu hỏi về một sự kiện khách quan. Chỉ vì ít người biết câu trả lời không đặt ra một câu hỏi chủ quan hoặc tranh luận. –

+0

@Eric, cho dù nó đến để thảo luận hay không không phải là một câu hỏi lập trình. Điều này sẽ trở thành "nên nó đã được thảo luận" hoặc "họ nên hỗ trợ nó", đó là chủ quan và tranh luận. –

Trả lời

24

Ủy ban thiết kế C# có bao giờ coi cú pháp tạo đối tượng này không?

Có, chúng tôi có. Chúng tôi đã xem nó một vài năm trước đây. Như bằng chứng về tuyên bố này, xem đoạn cuối cùng của bài viết của tôi ở đây:

http://blogs.msdn.com/b/ericlippert/archive/2009/01/26/why-no-var-on-fields.aspx

Sự đồng thuận của đội ngũ thiết kế là rằng đây là một "thú vị khi có" tính năng nhưng không đủ thuyết phục rằng đó là giá trị chi phí đáng kể về thiết kế, triển khai, thử nghiệm, ghi chép và duy trì tính năng này.

Tôi cũng lưu ý rằng các nhận xét về mục nhập blog mà tôi liên kết đến rất tiêu cực về tính năng này; có vẻ như rất nhiều người thấy cú pháp không hấp dẫn. Đó cũng là điểm chống lại việc thực hiện tính năng này.

Tuy nhiên, cú pháp được đề xuất trở nên đặc biệt tốt đẹp nếu bạn có thể kết hợp cú pháp với các tính năng ngôn ngữ khác quảng bá tuyên bố ngắn gọn về các loại không thể thay đổi; nếu chúng ta làm một tính năng như vậy trong một phiên bản tương lai giả định của ngôn ngữ, thì cú pháp bạn đề xuất sẽ trở nên hấp dẫn hơn.

Tôi lưu ý thêm rằng chúng tôi nói chung chống lại các tính năng yêu cầu suy luận từ "bên ngoài" thành "bên trong"; chúng tôi thích luồng thông tin kiểu đó từ trong ra ngoài.Hãy xem xét ví dụ vấn đề này:

M(new(blah)); 

Giả sử M có hai quá tải, một trong đó có một C, và một trong đó có một D. Có phải đó là "mới C (blah)" hoặc "mới D (blah)"? Nó có thể là một trong hai. Bây giờ chúng ta phải phân tích cả hai! Và nếu cả hai đều làm việc thì chúng ta phải tìm ra cái nào tốt hơn.

Nó trở nên tồi tệ hơn. Giả sử bạn có

M(new(new(blah))); 

nơi một lần nữa M mất một C và D, và C có hai cấu trúc mà phải mất một E hoặc F, và D có hai cấu trúc mà phải mất một G và H. nào:

M(new C(new E(blah))); 
M(new C(new F(blah))); 
M(new D(new G(blah))); 
M(new D(new H(blah))); 

được chọn và tại sao?

Khi bạn lý do từ bên ngoài vào bên trong, bạn nhanh chóng vào "các vụ nổ kết hợp", trong đó số trường hợp cần phân tích trở thành O (c n) ở độ sâu của lồng.

C# làm lý do theo cách này cho lambdas và đó là một trong những phần khó nhất của trình biên dịch để thực hiện và chính xác, tin tôi đi. Chúng tôi không mong muốn thêm một tính năng tương tự cho các nhà xây dựng. Nếu chúng ta thêm cú pháp này, nó có lẽ sẽ bị giới hạn trong các kịch bản trong đó loại được biết rõ ràng bằng cách phân tích phía bên trái của một khai báo biến hoặc biểu thức gán.

(Như mọi khi, tôi lưu ý rằng các suy nghĩ của Eric về các tính năng ngôn ngữ tương lai giả định trong các sản phẩm không báo trước và hư cấu không có lịch biểu hoặc ngân sách chỉ dành cho mục đích giải trí và không được hiểu là lời hứa của bất kỳ sản phẩm cụ thể nào trong tương lai với bất kỳ bộ tính năng đặc biệt)

+3

Tôi muốn nghe nhiều hơn về ý tưởng của bạn về các tính năng giả thuyết giúp làm việc với các loại không thay đổi dễ dàng hơn. Việc thiếu hỗ trợ ngôn ngữ trong khu vực đó là một trong những phiền toái chính của tôi với C# hiện tại. – CodesInChaos

+1

@CodeInChaos: Tính năng này quá sáng suốt vào thời điểm này để thậm chí là blog về nó; những ý tưởng chúng tôi đã xoay quanh chủ yếu xoay quanh một cú pháp ngắn gọn để nói "đây là một bản ghi bất biến" và sau đó có các hàm tạo và các đặc tính truy cập được tạo tự động cho bạn - giống như các kiểu ẩn danh. Ngay bây giờ có rất nhiều "lễ" xung quanh tuyên bố một loại bất biến dẫn đến rất nhiều mã boilerplate nhàm chán. Nó sẽ là tốt đẹp để loại bỏ nó. –

+0

Nhưng bạn có 'int [] f = {1, 2, 3};' trong C#, tôi có nghĩa là quá bên ngoài. Tôi nghĩ C# có thể gây ra lỗi mơ hồ khi loại không được đề cập ở bên trái hoặc bên phải, biên dịch nếu loại chỉ được đề cập ở một trong hai bên và ngăn chặn nếu phải và trái đánh giá sai biểu thức .. – nawfal

0

Không chắc chắn về điều đó nhưng nếu bạn muốn giữ mọi thứ ở bên trái, bạn có thể sử dụng:

var dataEntities = new DataService1.DataEntities(constructorArg1, ...) 
+1

Phần thứ hai của bài viết của ông nói về điều này, tôi nghĩ vậy. –

+3

tôi đã đề cập rằng trong đoạn cuối của nhiệm vụ của tôi –

2

Nó xâm nhập từ phía bên trái về phía sau biểu thức. Và nếu biểu thức là không tầm thường mà xấu xí khá nhanh.

Bạn có thể hiểu biểu thức bằng cách chỉ nhìn vào biểu thức gần như luôn luôn (ngoại trừ một số suy luận kiểu lamda), và điều đó là không thể với cú pháp của bạn. Với lamdas, độ lợi là khá lớn, do đó suy luận phức tạp là một sự cân bằng tốt cho các lệnh lamdas, nhưng việc thêm độ phức tạp đó cho một tính năng tầm thường như vậy là một sự đánh đổi xấu cho việc khởi tạo biến đơn giản.

Trường hợp đặc biệt có thể "gán cho biến nơi biểu thức ngoài cùng bên phải là biểu thức new". Nghe có vẻ rất không thích hợp với tôi. Đặc biệt là kể từ khi tính năng var đã đạt được một cái gì đó rất giống nhau, trong khi linh hoạt hơn.

+0

(ảnh ngẫu nhiên ở đây) nếu nó là "fooType fooIdent = var (arg1, ...)"? liệu tính duy nhất của từ khóa var có tham số làm cho nó hoạt động? Đó là - var (..) sẽ được thay thế bằng T mới, và T là bất cứ kiểu biểu thức nào ở bên trái. –

+0

Điều đó vẫn có vấn đề về suy luận kiểu từ kết quả vào trong. Nếu bạn chỉ thấy 'var (arg1, ...)' bạn vẫn không biết ý nghĩa của nó. Kiểu suy luận kiểu này chắc chắn là có thể, nhưng tôi tránh nó trừ phi lợi ích là đáng kể. – CodesInChaos

+0

nếu tôi đọc bìa sách Dragon để trang trải thì tôi có hiểu không? :) –

0

Cũng như thế nào về việc có:.

DataType dt; 

trung bình giống như:

DataType dt = new DataType(); 

Và sau đó:

DataType dt = { ParamOne = 1, ParamTwo = 2 }; 

là giống như:

DataType dt = new DataType(){ ParamOne = 1, ParamTwo =2 }; 
+5

Chắc chắn ** không **. 'DataType dt;' không, và không nên nhầm lẫn, giống như 'DataType dt = new DataType();'. Cái thứ hai gọi một hàm tạo, đó là một sự phân biệt quan trọng cần được giữ nguyên trong cú pháp. –

+1

Rõ ràng nó sẽ không phù hợp với ngôn ngữ hiện tại của C#. Ở tất cả. Nhưng ưu tiên của tôi vào thời điểm này là chuyển sang một ngôn ngữ không có null ở khắp mọi nơi. Lỗi phổ biến nhất mà tôi thấy trong mã là lỗi "tham chiếu null". Mà, chắc chắn, đến từ lập trình cẩu thả, nhưng cũng (như tôi thấy nó) một lỗ hổng trong thiết kế của C# như một ngôn ngữ.Nó cũng là một trở kháng không phù hợp với cách một số loại công việc (như int). – mlibby

+0

Các ngôn ngữ không có khái niệm 'null' đã được xem xét trước đây, nhưng chúng không thực sự hoạt động. Cũng giống như hệ thống số mà không có khái niệm về 0. Bạn quá hạn chế về tính biểu cảm mà không có khả năng thể hiện, tốt, không có gì. Bây giờ, nếu bạn đang tranh luận rằng C# nên di chuyển nhiều hơn về phía thành ngữ RAII (như được tìm thấy trong C++), sau đó tôi có thể nghiêng nhiều hơn để đồng ý với bạn. Có rất nhiều vấn đề với mẫu 'IDisposable', và tôi nghĩ đây là nguồn của nhiều lỗi hơn tham chiếu null (đặc biệt là vì NRE có thể dễ dàng bị bắt gặp lúc gỡ lỗi, trong khi rò rỉ bộ nhớ thì khó hơn). –

2

Nếu bạn muốn tạo một đối tượng của loại giống như các thành viên sử dụng để lưu trữ nó mà không cần phải lặp lại tên loại, bạn có thể sử dụng "Stockton mới". Nhược điểm là bạn phải lặp lại tên thành viên trong quá trình khởi tạo. Đây là cách có vẻ:

class Program 
    { 
       private static T New<T>(out T item) where T : new() 
       { 
           item = new T(); 

           return item; 
       } 

       static Dictionary<Int32, Int32> _member = New(out _member); 

       static void Main(string[] args) 
       { 
           Dictionary<Int32, Int32> local = New(out local); 
       } 
} 

Bên cạnh đó, chúng ta có thể mở rộng phương pháp này để tạo các lớp bê tông cho các giao diện tương ứng với một vài quá tải đơn giản:

public static IDictionary<TKey, TValue> New<TKey, TValue>(out IDictionary<TKey, TValue> item) 
{ 
     item = new Dictionary<TKey, TValue>(); 

     return item; 
} 

public static IList<T> New<T>(out IList<T> item) 
{ 
     item = new List<T>(); 

     return item; 
} 

Bây giờ bạn có thể viết này:

IDictionary<Int32, Int32> local = New(out local); 

Một sự ghê tởm, sự tò mò hoặc một kỹ thuật hữu ích? Bạn quyết định.

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