2011-01-29 30 views
15
public class Sample 
{ 
    static int count = 0; 
    public int abc; 
    public Sample() 
    { 
     abc = ++Sample.count; 
    } 
} 

Tôi muốn tạo ra một loạt các lớp trên, và muốn mỗi phần tử trong mảng được khởi tạo bằng cách gọi các constructor mặc định, do đó mỗi phần tử có thể có khác nhau abc Vì vậy, tôi đã làm điều này :Mảng khởi với constructor mặc định

Sample[] samples = new Sample[100]; 

Nhưng điều này không làm những gì tôi nghĩ rằng nó nên làm. Có vẻ như cách này constructor mặc định không nhận được gọi. Làm thế nào để gọi constructor mặc định khi tạo một mảng?

Tôi cũng muốn biết câu lệnh trên làm gì?

+0

tại sao bạn không chỉ cần sử dụng chỉ số mảng, gia tăng độc đáo và tự động của nó theo mã của bạn –

+2

Trên một mặt lưu ý - mã mà không phải là thread-safe; bạn nên sử dụng 'id = Interlocked.Increment (ref count)' thay vào đó, và bắt đầu với 'static int count = 1' (vì' Interlocked.Increment' trả về giá trị * cũ *). –

+0

cũng trong đoạn mã trên bạn vừa khai báo một mảng có kích thước 100, không có mục nào trong đó. – Victor

Trả lời

38

Bạn không thể, về cơ bản. Khi bạn tạo một mảng, nó luôn được điền ban đầu với giá trị mặc định cho loại - mà cho một lớp luôn là tham chiếu null. Đối với int đã ghi bàn 0, cho bool đó là sai vv

(Nếu bạn sử dụng một initializer mảng, mà sẽ tạo ra "trống rỗng" mảng và sau đó cư nó với các giá trị mà bạn đã chỉ định, tất nhiên.)

Có nhiều cách khác nhau để điền vào mảng bằng cách gọi hàm dựng - tôi có thể có lẽ là chỉ sử dụng vòng lặp foreach. Sử dụng LINQ với Enumerable.Range/Lặp lại cảm thấy một chút buộc.

Tất nhiên, bạn luôn có có thể viết phương pháp dân riêng của bạn, thậm chí như một phương pháp khuyến nông:

public static T[] Populate<T>(this T[] array, Func<T> provider) 
{ 
    for (int i = 0; i < array.Length; i++) 
    { 
     array[i] = provider(); 
    } 
    return array; 
} 

Sau đó, bạn có thể sử dụng:

Sample[] samples = new Sample[100].Populate(() => new Sample()); 

Những gì tôi thích về giải pháp này:

  • Nó vẫn là một biểu thức duy nhất, có thể hữu ích trong nhiều kịch bản
  • Nó không giới thiệu các khái niệm bạn không thực sự muốn (như lặp đi lặp lại một giá trị duy nhất hoặc tạo ra một phạm vi)

Tất nhiên bạn có thể thêm nhiều lựa chọn:

  • Một tình trạng quá tải mà mất một Func<int, T> thay vì một Func<T>, đi qua các chỉ số để các nhà cung cấp
  • một phương pháp không gia hạn mà tạo ra các mảng populates nó
+2

Tôi thích giải pháp này nhất. :-) Phương pháp tái sử dụng. :-) – Nawaz

+2

Một quá tải hữu ích khác là thay thế ', Func nhà cung cấp)' với ') trong đó T: new()' và sau đó bạn không cần chuyển giao một đại biểu nếu bạn chỉ sử dụng hàm tạo mặc định (bạn cũng sẽ cần phải thay thế 'provider()' bằng 'new T()'). –

4

Không có cách nào để thực hiện điều này tự động; khởi tạo mảng về bản chất là "xóa khối bộ nhớ này thành 0". Bạn sẽ phải làm một cái gì đó như:

var arr = new SomeType[size]; 
for(int i = 0 ; i < size ; i++) arr[i] = new SomeType(); 
8

Mã của bạn chỉ tạo mảng, nhưng không ai trong số các mục của nó. Về cơ bản, bạn cần phải trường hợp cửa hàng của Samplethành mảng này.

Nói một cách đơn giản, mà không cần bất kỳ ưa thích LINQ v.v .:

Sample[] samples = new Sample[100]; 
for (int i = 0; i < samples.Length; i++) samples[i] = new Sample(); 

Xin lưu ý giải pháp của bạn là không thread-safe.

2

Vấn đề là bằng cách khai báo mảng đó, bạn không bao giờ phân bổ không gian cho từng đối tượng. Bạn chỉ phân bổ không gian cho 100 đối tượng kiểu mẫu. Bạn sẽ phải gọi cho nhà xây dựng trên mỗi chính bạn.

Xây dựng:

Food[] foods = Food[100]; 
for (int k = 0; k < foods.length; k++) { 
    foods[k] = new Food(); 
} 

Một công việc thú vị xung quanh có thể là một chức năng nhà máy. Xem xét việc gắn nó vào lớp Sample của bạn.

public static Sample[] getInstances(int aNumber) { 
    Sample[] sample = Sample[aNumber]; 
    for (int k = 0; k < sample.length; k++) { 
     sample[k] = new Sample(); 
    } 

    return sample; 
} 

Ẩn nhược điểm, cung cấp chức năng này hữu ích cho bạn.

+0

Vì vậy, đó là mã tối thiểu mà tôi phải viết? – Nawaz

+0

Tôi đã chỉnh sửa nó bằng một giải pháp mà bạn có thể thích. Câu trả lời ngắn gọn là có, mặc dù. :/ – Mike

+0

Bạn đang tạo mảng 'Food' nhưng kiểu trả về là' Sample [] ': P – Nawaz

2

Tại thời điểm này, bạn có một mảng trống kích thước 100, nếu bạn muốn điền vào nó với các vật phẩm, sau đó bạn sẽ phải làm một cái gì đó như:

for(int i=0; i<samples.Length; i++) { 
    samples[i] = new Sample(); 
} 
1

Dưới đây là một one-liner điều đó không' t yêu cầu bất kỳ phương pháp khuyến nông:

Sample[] array = Enumerable.Range(0, 100).Select(i => new Sample()).ToArray(); 

Một tùy chọn khác tốt đẹp là Scott's suggestion-Jon's answer:

public static T[] Populate<T>(this T[] array) 
    where T : new() 
{ 
    for (int i = 0; i < array.Length; i++) 
     array[i] = new T(); 
    return array; 
} 

Vì vậy, bạn có thể làm:

Sample[] array = new Sample[100].Populate(); 
Các vấn đề liên quan