2015-11-25 29 views
23

Tôi tình cờ gặp một phương pháp ngay hôm nay. Tôi đang nói về: Array.Initialize().Array.Initialize - Tại sao phương pháp này tồn tại?

Theo tài liệu:

This method is designed to help compilers support value-type arrays; most users do not need this method.

Làm thế nào để phương pháp này có trách nhiệm làm cho các loại giá trị biên dịch hỗ trợ? Theo như tôi lo ngại phương pháp này chỉ:

Initializes every element of the value-type Array by calling the default constructor of the value type.

Ngoài ra, tại sao nó công? Tôi không thấy bản thân mình với sự cần thiết phải gọi phương thức này, các trình biên dịch đã khởi tạo các mảng khi được tạo ra, do đó việc gọi thủ công phương thức này sẽ là thừa và vô ích.

Ngay cả khi ý định của tôi sẽ đặt lại giá trị của một mảng, tôi vẫn không gọi nó, tôi sẽ tạo một giá trị mới. array = new int[].

Vì vậy, có vẻ như phương pháp này tồn tại chỉ vì lợi ích của trình biên dịch. Tại sao điều này? Bất cứ ai có thể cho tôi một số chi tiết hơn?

+0

Và nếu bạn muốn đặt lại các giá trị mà không tạo mảng mới, có lẽ bạn cũng nên sử dụng 'Array.Clear()'. –

+8

Đóng phiếu bầu? Điều này có vẻ là một câu hỏi hợp lệ với tôi. Có lẽ bạn đã bỏ phiếu để đóng dựa trên tiêu đề? Tôi biết _Tại sao phương pháp này tồn tại_ là một số loại khó khăn nhưng nếu bạn đọc tất cả câu hỏi, tôi chắc chắn bạn sẽ đồng ý với tôi. –

+1

@ SonerGönül "Tại sao khuôn khổ được thiết kế theo cách này" là một câu hỏi về những người thiết kế nó có thể trả lời. Bất cứ ai khác chỉ là đoán được. Câu hỏi không phù hợp với SO; nếu bạn muốn biết tại sao Microsoft thiết kế .NET theo cách này, hãy hỏi * chúng *. – Servy

Trả lời

11

Cần lưu ý rằng các quy tắc của .NET khác với quy tắc của C#.

Có những thứ chúng ta có thể làm trong .NET mà chúng ta không thể làm trong C#, thường là do mã không thể xác minh (ví dụ: ref loại trả về) hoặc vì chúng có thể giới thiệu một số nhầm lẫn.

Trong C# struct s không thể có một constructor parameterless định nghĩa, và gọi new SomeValueType() công trình bằng cách tạo ra một phần zero-điền bộ nhớ (do đó tất cả các lĩnh vực là 0 với nhiều loại số, null với nhiều loại tài liệu tham khảo, và kết quả của quy tắc này tương tự một lần nữa cho các loại giá trị khác).

Trong .NET, bạn có thể có một hàm tạo parameterless trên một kiểu giá trị.

Có thể là một ý tưởng tồi khi làm như vậy. Đối với một điều quy tắc về chỉ khi nó được gọi và chỉ khi bộ nhớ của giá trị là không đầy, và những gì xảy ra khi chuyển nhượng trong các trường hợp khác nhau không hoàn toàn đơn giản (ví dụ: new SomeValueType() sẽ gọi nó là new T() theo phương pháp chung TSomeValueType sẽ không!). Cuộc sống đơn giản hơn nếu kết quả của new SomeValueType() sẽ luôn là không điền. Điều đó không có nghi ngờ ảnh hưởng đến thiết kế của C# không cho phép điều này mặc dù NET không. Vì lý do này, Array.Initialize() sẽ không bao giờ có ý nghĩa trên các mảng mới của bất kỳ kiểu nào được viết bằng C#, bởi vì việc gọi hàm tạo và không điền là giống nhau. Tuy nhiên, theo cùng một mã thông báo, có thể một loại được viết bằng ngôn ngữ .NET khác (ít nhất, bạn có thể thực hiện nó trong CIL) có một hàm tạo tham số thực sự có hiệu lực. Và vì lý do đó, có thể trình biên dịch cho một ngôn ngữ như vậy sẽ tương đương với new SomeValueType[3] để gọi hàm tạo đó trên tất cả các kiểu trong mảng. Và do đó nó hợp lý để có một phương pháp trong khuôn khổ cho phép điền như vậy để được thực hiện, để một trình biên dịch cho một ngôn ngữ như vậy có thể tận dụng nó.

Also, why is it public?

Vì vậy, nó có thể được gọi bằng mã do một nhà xây dựng giả thiết tạo ra ngay cả trong bối cảnh hạn chế bảo mật không cho phép gọi phương thức riêng của hội đồng khác.

+1

"Bây giờ bạn có thể làm điều này với C# 6": không, bạn không thể. Tính năng này đã được xem xét và IIRC thậm chí nó đã được triển khai ở một trong các phiên bản tiền phát hành, nhưng cuối cùng nó đã bị rút lại. Trong phiên bản cuối cùng, bạn nhận được lỗi này: 'CS0568 Structs không thể chứa các hàm tạo tham số rõ ràng –

+1

@ThomasLevesque ah, cảm ơn, bạn có thể nói rằng tôi chưa thực sự chơi với phiên bản mới nhất! Cũng tốt! Các vagueries của các nhà xây dựng parameterless trên các loại giá trị có thể sẽ không có giá trị nó. –

1

Đối với bản thân tôi, có vẻ như phương thức Initialize() chạy qua mảng và tạo lại các loại giá trị Giá trị bên trong. Vì vậy, với một mảng mới bạn nhận được một mảng trống mới và do đó bạn nhận được với Array.Clear(), nhưng với Array.Initialize() bạn nhận được một mảng đầy đủ các tạo loại Value tươi (chủng loại và chiều dài dựa trên mảng cũ).

Và đó sẽ là tất cả sự khác biệt.

+0

Giả sử tôi có 'int [] a = new int [3] {7, 9, 13,};' trong C#. Câu trả lời của bạn _could_ được đọc là có nghĩa là nếu tôi làm 'a.Initialize();' trên đó, thì tôi sẽ có một dãy số không ('mặc định (int)') sau đó. Điều này là sai, tuy nhiên. Nếu bạn muốn tính năng đó, sử dụng 'Array.Clear (a, 0, a.Length);' thay vào đó. –

0

Dựa trên CLR source, phương thức di chuyển từng chỉ mục của mảng và khởi tạo kiểu giá trị trên chỉ mục đó bằng cách gọi hàm tạo mặc định, tương tự như hướng dẫn initobj IL (tôi tự hỏi điều gì sẽ xảy ra khi hàm tạo ném ngoại lệ) . Phương thức này là công khai vì việc gọi phương thức riêng trực tiếp từ IL sẽ làm cho nó không thể xác minh được một chút.

Trình biên dịch C# của ngày hôm nay không khởi tạo từng phần tử của mảng khi tạo, chỉ cần "đặt" từng chỉ mục thành giá trị mặc định của loại. C# 6 giới thiệu việc triển khai các hàm tạo mặc định cho các kiểu giá trị (đã được CLR hỗ trợ), vì vậy điều này là cần thiết cho các ngôn ngữ với các ngữ nghĩa tạo mảng khác nhau.

0

Bạn có thể thấy việc sử dụng dự kiến ​​trong mã kiểm tra:

https://github.com/dotnet/coreclr/blob/3015ff7afb4936a1c5c5856daa4e3482e6b390a9/tests/src/CoreMangLib/cti/system/array/arrayinitialize.cs

Về cơ bản, nó đặt một loạt các phi thực chất giá trị các loại trở lại mặc định của họ (T) nhà nước.

Nó không có vẻ giống như một công cụ hữu ích đáng kinh ngạc, nhưng tôi có thể thấy nó có thể hữu ích như thế nào cho việc không tạo ra mảng dữ liệu giá trị không nội tại.

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