Làm cách nào để khởi tạo một mảng trống trong C #?


328

Có thể tạo một mảng trống mà không chỉ định kích thước?

Ví dụ: tôi đã tạo:

String[] a = new String[5];

Chúng ta có thể tạo mảng chuỗi trên mà không có kích thước không?


2
stackoverflow.com/questions/151936/ Đăng u kiểm tra liên kết này, nó có thể giúp bạn hiểu rõ mọi thứ về mảng
Ravi Gadag

Câu trả lời:


435

Nếu bạn định sử dụng một bộ sưu tập mà bạn không biết kích thước trước, có những lựa chọn tốt hơn so với mảng.

Sử dụng List<string>thay thế - nó sẽ cho phép bạn thêm bao nhiêu mục bạn cần và nếu bạn cần trả về một mảng, hãy gọi ToArray()biến.

var listOfStrings = new List<string>();

// do stuff...

string[] arrayOfStrings = listOfStrings.ToArray();

Nếu bạn phải tạo một mảng trống, bạn có thể làm điều này:

string[] emptyStringArray = new string[0]; 

1
@Oded - chuỗi [] blankStringArray = chuỗi mới [0]; không dẫn đến một mảng trống, phải không? Dường như đó là một mảng với một phần tử trong đó phần tử đó là null.
rory.ap

11
@roryap - Không. Kết quả là string[]không có yếu tố nào. Nếu bạn cố gắng truy cập emptyStringArray[0], bạn sẽ nhận đượcIndexOutOfRangeException
Oded

@Oded - Cảm ơn, tôi khá mới với C #. Trong VB, chỉ số được cung cấp là giới hạn trên, không phải số lượng phần tử.
rory.ap

1
Những gì bạn sẽ xem xét tốt hơn: var chuỗi = chuỗi mới [] {}; hoặc chuỗi var = chuỗi mới [0]; BTW: Tôi coi một mảng trống là mặc định hoàn toàn hợp lệ cho các tham số phương thức: public void EditItems (IEnumerable <Item> toEdit, IEnumerable <long> toDelete = new long [] {})
realbart

6
@ RickO'Shea - C ++ không phải là C #. Stroustrup biết C ++ của anh ấy - không chắc anh ấy biết C # và .NET GC của mình. Sẽ không đi vào một cuộc chiến tôn giáo với bạn.
Oded

181

Thử cái này:

string[] a = new string[] { };

7
Mở rộng câu trả lời này, bạn cũng có thể khởi tạo mảng với các mục mà không chỉ định kích thước loại OR, trình biên dịch sẽ suy ra từ trình khởi tạo: var a = new [] {"a", "b", "c"}; Đây vẫn là một chuỗi chuỗi gõ mạnh.
Nick VanderPyle

1
Ngoại lệ chưa được xử lý: System.IndexOutOfRangeException: Index nằm ngoài bouns của mảng. tại ArrayClass.Main (Chuỗi [] args). Tôi đã gặp phải lỗi này sau khi tôi thay đổi int [] biến = new int [] {}
Yogesh

6
@yogesh: Thật lạ. Khi ví dụ viết int[] variable = new int[]{}và sử dụng nó chẳng hạn trong một vòng lặp, chẳng hạn như foreach (var s in variable){ Console.WriteLine(s);}mã được biên dịch thành: int[] args1 = new int[0];foreach (int num in args1){Console.WriteLine(num);}. Vì vậy, không nên có sự khác biệt giữa việc sử dụng new int[0]new int[]{}vì cả hai đều được biên dịch thành cùng một mã.
Không có

1
@GlennGordon Hoàn toàn, nhưng đó là phiên bản mới của C # 3.0 (từ năm 2007, với Visual Studio 2008). Phiên bản đó cũng cho phép một định dạng đơn giản khác var, mặc dù chỉ dành cho các biến cục bộ (không phải cho các trường). Tuy nhiên, trong C # 2.0 (Visual Studio 2005) trở về trước, bạn phải sử dụng cú pháp của câu trả lời này (hoặc string[] a = new string[0];).
Jeppe Stig Nielsen

113

Trong .NET 4.6, cách ưa thích là sử dụng một phương thức mới , Array.Empty:

String[] a = Array.Empty<string>();

Việc triển khai ngắn gọn, sử dụng cách các thành viên tĩnh trong các lớp chung hoạt động trong .Net :

public static T[] Empty<T>()
{
    return EmptyArray<T>.Value;
}

// Useful in number of places that return an empty byte array to avoid
// unnecessary memory allocation.
internal static class EmptyArray<T>
{
    public static readonly T[] Value = new T[0];
}

(mã hợp đồng liên quan đến mã bị loại bỏ cho rõ ràng)

Xem thêm:


@Cole Johnson - Cảm ơn bạn đã chỉnh sửa, nhưng tôi đã khôi phục nó. Tôi đã bỏ qua những dòng này trên mục đích: Tôi muốn chỉ trích dẫn việc thực hiện thú vị. Hợp đồng mã và các thuộc tính chỉ có cách hiểu những gì đang xảy ra (tất nhiên liên kết đến nguồn có tất cả mọi thứ). Tôi cũng đã thêm một dòng mới trong bình luận để tránh cuộn trên Stack Overflow. Nếu bạn không phiền, tôi thích nó theo cách này. Cảm ơn!
Kobi

2
Chắc chắn là một cải tiến cho khả năng đọc từ:Enumerable.Empty<T>().ToArray()
DanielV

Mặc dù phương pháp này chắc chắn được ưa thích trong hầu hết các trường hợp, nó không trả lời câu hỏi ban đầu. OP muốn tạo một mảng trống. Array.Empty<T>()không không tạo ra một mảng. Nó trả về một tham chiếu đến một mảng được phân bổ trước.
l33t

33

Bạn có thể khởi tạo nó với kích thước bằng 0, nhưng bạn sẽ phải xác định lại nó, khi bạn biết kích thước đó là gì, vì bạn không thể nối thêm vào mảng.

string[] a = new string[0];

Đây là câu trả lời chính xác
abzarak

7

Không có nhiều điểm trong việc khai báo một mảng không có kích thước. Một mảng có kích thước . Khi bạn khai báo một mảng có kích thước cụ thể, bạn chỉ định số lượng vị trí cố định có sẵn trong bộ sưu tập có thể chứa mọi thứ và bộ nhớ theo đó được phân bổ. Để thêm một cái gì đó vào nó, dù sao bạn cũng cần phải xác định lại mảng hiện có (ngay cả khi bạn đang thay đổi kích thước mảng, hãy xem chủ đề này ). Một trong những trường hợp hiếm hoi mà bạn muốn khởi tạo một mảng trống sẽ là truyền mảng làm đối số.

Nếu bạn muốn xác định một bộ sưu tập khi bạn không biết nó có thể có kích thước như thế nào, thì mảng không phải là lựa chọn của bạn, mà là một cái gì đó giống như List<T>hoặc tương tự.

Điều đó nói rằng, cách duy nhất để khai báo một mảng mà không chỉ định kích thước là có một mảng trống có kích thước 0 . hemantAlex Dn cung cấp hai cách. Một cách khác đơn giản hơn là chỉ :

string[] a = { };

[ Ví dụ, các phần tử bên trong khung phải được chuyển đổi hoàn toàn thành loại được xác định,string[] a = { "a", "b" }; ]

Hoặc khác:

var a = Enumerable.Empty<string>().ToArray();

Đây là một cách khai báo hơn :

public static class Array<T>
{
    public static T[] Empty()
    {
        return Empty(0);
    }

    public static T[] Empty(int size)
    {
        return new T[size];
    }
}

Bây giờ bạn có thể gọi:

var a = Array<string>.Empty();

//or

var a = Array<string>.Empty(5);

1
Tôi không thể nghĩ về bất kỳ việc sử dụng nào trừ khi bạn phải truyền một mảng làm tham số. Có một vài trường hợp phản ánh trong đó một phương thức chấp nhận một mảng các đối tượng và bạn có thể muốn truyền một mảng trống để thực hiện hành động mặc định. Tôi sẽ chỉnh sửa câu trả lời của tôi.
nawfal

Ví dụ, bạn có một giao diện được triển khai bởi một số lớp trả về IEnumerable và một trong các triển khai không có các phần tử cho phương thức và trả về một mảng trống chẳng hạn.
Ignacio Soler Garcia

@IgnacioSolerGarcia Tôi sẽ trả về một mảng trong trường hợp đó nếu và chỉ khi đó là một ứng dụng cực kỳ hiệu năng. Tôi sẽ nói các mảng đã lỗi thời và nên tránh nếu bạn có thể. Xem điều này bởi Lippertcâu hỏi SO này
nawfal

Hãy nhớ rằng kiểu trả về là IEnumerable nên mảng chỉ đọc và nó không có ý định thay đổi. Tại sao tôi sẽ trả lại một Danh sách trong trường hợp này chẳng hạn?
Ignacio Soler Garcia

1
Trường hợp sử dụng cho một mảng trống rất đơn giản - khi bạn muốn điền nó vào các đối tượng và bạn không biết bạn sẽ thêm bao nhiêu!
vapcguy

6

Đơn giản và thanh lịch!

string[] array = {}

Tôi sẽ thay đổi arraythành chỉ a, như arraylà một từ khóa khi viết hoa. Chỉ cần thực hành xấu để sử dụng tên từ khóa làm tên biến - ngay cả khi trường hợp khác. Và về cơ bản giống như câu trả lời của tôi ngoại trừ tôi có String.Emptytrong đó.
vapcguy

1
1. mảng không phải là từ khóa ac #. Mảng là một lớp và không phải là một từ khóa 2. "a" cũng là một thực tiễn tồi (thậm chí có thể còn tệ hơn một thực tiễn xấu so với sử dụng từ khóa)
đĩalosr

Là kỹ thuật. Lớp, từ khóa, nó định nghĩa một loại đối tượng và vẫn còn xấu. Tại sao bạn nghĩ alà xấu?
vapcguy

1
Bởi vì tên biến không mô tả và một chữ cái là thực tiễn xấu vì chúng không truyền đạt lý do đằng sau việc xác định chúng. "Mảng" chắc chắn là một cái tên tốt hơn "a". Một cái tên tốt hơn sẽ là "blankArray".
Disclosr

4

string[] a = new string[0];

hoặc ký hiệu ngắn:

string[] a = { };

Cách ưa thích bây giờ là:

var a = Array.Empty<string>();

Tôi đã viết một biểu thức chính quy ngắn mà bạn có thể sử dụng trong Visual Studio nếu bạn muốn thay thế phân bổ độ dài bằng không, ví dụ new string[0]. Sử dụng Tìm kiếm (tìm kiếm) trong Visual Studio với tùy chọn Biểu thức chính quy được bật:

new[ ][a-zA-Z0-9]+\[0\]

Bây giờ Tìm tất cả hoặc F3 (Tìm tiếp theo) và thay thế tất cả bằng Array.Empty <trộm> ()!


3

Bạn có thể xác định kích thước mảng khi chạy .

Điều này sẽ cho phép bạn làm bất cứ điều gì để tính toán linh hoạt kích thước của mảng. Nhưng, một khi xác định kích thước là bất biến.

Array a = Array.CreateInstance(typeof(string), 5);

4
Tại sao làm tất cả những điều đó? Trong thời gian chạy, bạn có thể xác định kích thước mảng từ một biến thông thường:int i = 5; string[] a = new string[i];
Kevin Brock

Chà, tôi đoán với thuốc generic này dường như đã lỗi thời.
radarbob

2

Tôi đã thử:

string[] sample = new string[0];

Nhưng tôi chỉ có thể chèn một chuỗi vào nó và sau đó tôi đã gặp lỗi ngoại lệOutOfBound, vì vậy tôi chỉ cần đặt một kích thước cho nó, như

string[] sample = new string[100];

Hoặc một cách khác phù hợp với tôi:

List<string> sample = new List<string>();

Gán giá trị cho danh sách:

sample.Add(your input);

1

Như tôi biết bạn không thể tạo mảng mà không có kích thước, nhưng bạn có thể sử dụng

List<string> l = new List<string>() 

và sau đó l.ToArray().


1

Kết hợp các đề xuất @nawfal & @Kobi:

namespace Extensions
{
    /// <summary> Useful in number of places that return an empty byte array to avoid unnecessary memory allocation. </summary>
    public static class Array<T>
    {
        public static readonly T[] Empty = new T[0];
    }
}

Ví dụ sử dụng:

Array<string>.Empty

CẬP NHẬT 2019-05-14

(tín dụng cho @Jaider ty)

Sử dụng tốt hơn .Net API:

public static T[] Empty<T> ();

https://docs.microsoft.com/en-us/dotnet/api/system.array.empty?view=netframework-4.8

Áp dụng cho:

.NET Core: 3.0 Xem trước 5 2.2 2.1 2.0 1.1 1.0

.NET Framework: 4.8 4.7.2 4.7.1 4.7 4.6.2 4.6.1 4.6

Tiêu chuẩn .NET: 2.1 Xem trước 2.0 1.6 1.5 1.4 1.3

...

HTH


1
Trong .NET Core 2, đã có một phần mở rộng cho nó,arr = Array.Empty<string>();
Jaider

iirc, trong .NetStandart [4.s Something] - cũng có.
ShloEmi

0

Bạn có thể làm:

string[] a = { String.Empty };

Lưu ý: OP có nghĩa là không cần phải chỉ định kích thước, không làm cho một mảng không có kích thước


8
Điều này sẽ không tạo ra một chuỗi chuỗi có độ dài 1?
Sumner Evans

Đúng, nhưng nó đã bị xóa. Và OP yêu cầu khai báo mảng mà không cần phải nêu kích thước - điều này phù hợp với điều đó.
vapcguy

Và điều đó xứng đáng với một downvote, tại sao? OP có nghĩa là không phải specifykích thước, không tạo ra một mảng sizeless.
vapcguy

1
@vapcguy Tôi là người downvoter. Tôi hối hận. Tôi đã chỉnh sửa câu trả lời của bạn để hủy bỏ downvote của tôi. Nhận xét của bạn làm cho câu hỏi hơi mơ hồ. Không chắc đó là ý nghĩa của OP.
nawfal

4
OP yêu cầu một mảng trống . Mảng này không trống.
Keith

0

Đây là một ví dụ thực tế. Trong trường hợp này, cần phải khởi tạo mảng foundFilestrước thành độ dài bằng không.

(Như đã nhấn mạnh trong các câu trả lời khác: Điều này khởi tạo không phải là một phần tử và đặc biệt không phải là một phần tử có chỉ số bằng 0 vì điều đó có nghĩa là mảng có độ dài 1. Mảng có độ dài bằng 0 sau dòng này!).

Nếu phần = string[0]bị bỏ qua, có lỗi trình biên dịch!

Điều này là do khối bắt mà không cần thiết. Trình biên dịch C # nhận ra đường dẫn mã, rằng hàm Directory.GetFiles()có thể ném Ngoại lệ, để mảng có thể không được khởi tạo.

Trước khi bất cứ ai nói, không xem xét lại ngoại lệ sẽ là xử lý lỗi xấu: Điều này không đúng. Xử lý lỗi phải phù hợp với yêu cầu.

Trong trường hợp này, giả định rằng chương trình sẽ tiếp tục trong trường hợp thư mục không thể đọc được và không phá vỡ - ví dụ tốt nhất là hàm truyền qua cấu trúc thư mục. Ở đây xử lý lỗi chỉ là đăng nhập nó. Tất nhiên điều này có thể được thực hiện tốt hơn, ví dụ như thu thập tất cả các thư mục với GetFiles(Dir)các cuộc gọi thất bại trong danh sách, nhưng điều này sẽ dẫn quá xa đến đây.

Nó là đủ để nói rằng tránh throwlà một kịch bản hợp lệ, và do đó, mảng phải được khởi tạo với độ dài bằng không. Nó là đủ để làm điều này trong khối bắt, nhưng đây sẽ là phong cách xấu.

Cuộc gọi để GetFiles(Dir)thay đổi kích thước mảng.

string[] foundFiles= new string[0];
string dir = @"c:\";
try
{
    foundFiles = Directory.GetFiles(dir);  // Remark; Array is resized from length zero
}
// Please add appropriate Exception handling yourself
catch (IOException)
{
  Console.WriteLine("Log: Warning! IOException while reading directory: " + dir);
  // throw; // This would throw Exception to caller and avoid compiler error
}

foreach (string filename in foundFiles)
    Console.WriteLine("Filename: " + filename);
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.