2009-01-20 50 views
93

Trong C#, có một lối tắt nội tuyến để khởi tạo Danh sách <T> chỉ với một mục hay không.Phím tắt để tạo danh sách mục đơn trong C#

tôi đang thực hiện:

new List<string>(new string[] { "title" })) 

Có mã này ở khắp mọi nơi giảm khả năng đọc. Tôi đã nghĩ đến việc sử dụng một phương pháp hữu ích như thế này:

public static List<T> SingleItemList<T>(T value) 
{ 
    return (new List<T>(new T[] { value })); 
} 

Vì vậy, tôi có thể làm:

SingleItemList("title"); 

Có một/cách bụi ngắn hơn?

Cảm ơn.

Trả lời

168

Đơn giản chỉ cần sử dụng này:

List<string> list = new List<string>() { "single value" }; 

Bạn thậm chí có thể bỏ qua() niềng răng:

List<string> list = new List<string> { "single value" }; 

Cập nhật: tất nhiên điều này cũng làm việc cho nhiều hơn một entry:

List<string> list = new List<string> { "value1", "value2", ... }; 
+4

đặt 1 chữ cái trong dấu ngoặc đơn của tùy chọn đầu tiên, để lưu trữ chính xác một không gian được cấp phát thay vì mặc định 10 –

+4

Mặc định kết thúc bằng 4, tôi tin: Danh sách mới {"Hello"} .Capacity == 4 –

7

Sử dụng một phương pháp tiện ích mở rộng với chuỗi phương pháp.

public static List<T> WithItems(this List<T> list, params T[] items) 
{ 
    list.AddRange(items); 
    return list; 
} 

này sẽ cho phép bạn làm điều này:

List<string> strings = new List<string>().WithItems("Yes"); 

hoặc

List<string> strings = new List<string>().WithItems("Yes", "No", "Maybe So"); 

Cập nhật

Bây giờ bạn có thể sử dụng danh sách initializers:

var strings = new List<string> { "This", "That", "The Other" }; 

Xem http://msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx

+0

Có lẽ điều này là do các phiên bản mới hơn của C# từ năm 2009, nhưng tôi thấy 'Danh sách mới {" Có "}' để được tốt hơn ...? – ErikE

+0

@ErikE Theo tài liệu của Microsoft (http://msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx) điều này đã được hỗ trợ trong Visual Studio 2008. Tôi không thể nhớ rằng đến nay trở lại để nói dứt khoát nếu tôi quá phức tạp này vào thời điểm đó. Đang cập nhật. –

1

Bạn cũng có thể làm

new List<string>() { "string here" }; 
16

ý tưởng của việc sử dụng phương pháp khuyến nông của Michael dẫn đến một cái gì đó thậm chí đơn giản hơn:

public static List<T> InList(this T item) 
{ 
    return new List<T> { item }; 
} 

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

List<string> foo = "Hello".InList(); 

Tôi không chắc liệu tôi thích hay không, hãy nhớ ...

+0

Tôi cũng không chắc chắn tôi thích nó: không phải là một phần mở rộng "lạ" của loại chuỗi (ví dụ)? – M4N

+1

Tôi chưa đưa nó vào các phương pháp mở rộng trong sách của bạn, Jon :-) Điều này có vẻ lạ, nhưng tôi thích tiện ích của nó. Cảm ơn Martin và Jon. –

+2

@Martin: Đó là một phần mở rộng kỳ lạ của * mọi loại *. Điều này thường không được khuyến khích, nhưng đó là một ý tưởng chung thú vị. –

1

Tôi chỉ sẽ làm

var list = new List<string> { "hello" }; 
11

Một câu trả lời khác nhau để tôi sớm hơn một, dựa trên tiếp xúc với Google Java Collections:

public static class Lists 
{ 
    public static List<T> Of<T>(T item) 
    { 
     return new List<T> { item }; 
    } 
} 

Sau đó:

List<string> x = Lists.Of("Hello"); 

Tôi khuyên kiểm tra ra GJC - nó có rất nhiều thứ thú vị. (Cá nhân tôi bỏ qua thẻ "alpha" - nó chỉ là ông phiên bản mã nguồn mở là "alpha" và nó dựa trên một API nội bộ rất ổn định và sử dụng nhiều.)

30
var list = new List<string>(1) { "hello" }; 

Rất giống với những gì người khác đã được đăng, ngoại trừ việc nó làm cho chắc chắn để chỉ phân bổ không gian cho đĩa đơn mục ban đầu.

Tất nhiên, nếu bạn biết bạn sẽ thêm một loạt nội dung sau đó, đó có thể không phải là một ý tưởng hay nhưng vẫn đáng nhắc đến một lần.

+0

Dung lượng được đặt thành một. Tôi đã bình chọn cho bốn câu trả lời trên trang này bao gồm cả của Jon Skeet nhưng tôi coi đây là câu trả lời đúng nhất. –

0

Đối với một mục duy nhất liệt kê trong java, nó sẽ là Collections.singleton ("chuỗi");

Trong C# này sẽ là hiệu quả hơn so với một danh sách mới:

public class SingleEnumerator<T> : IEnumerable<T> 
{ 
    private readonly T m_Value; 

    public SingleEnumerator(T value) 
    { 
     m_Value = value; 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     yield return m_Value; 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     yield return m_Value; 
    } 
} 

nhưng là có một cách đơn giản hơn sử dụng khuôn khổ?

2

Tôi đã có chức năng này chút:

public static class CoreUtil 
{  
    public static IEnumerable<T> ToEnumerable<T>(params T[] items) 
    { 
     return items; 
    } 
} 

Vì nó không quy định một kiểu trả về bê tông này là rất chung chung mà tôi sử dụng nó khắp nơi. Mã của bạn sẽ trông như thế

CoreUtil.ToEnumerable("title").ToList(); 

Nhưng tất nhiên nó cũng cho phép

CoreUtil.ToEnumerable("title1", "title2", "title3").ToArray(); 

Tôi thường sử dụng nó trong khi tôi phải bổ sung/thêm vào trước một mục để đầu ra của một tuyên bố LINQ. Ví dụ để thêm một mục trống để một danh sách lựa chọn:

CoreUtil.ToEnumerable("").Concat(context.TrialTypes.Select(t => t.Name)) 

Tiết kiệm một vài ToList()Add báo cáo.

(Hậu trả lời, nhưng tôi stumbled khi oldie này và nghĩ rằng điều này có thể hữu ích)

1

Lấy cảm hứng từ câu trả lời khác (và vì vậy tôi có thể nhặt nó lên bất cứ khi nào tôi cần nó!), Nhưng với cách đặt tên/phong cách phù hợp với F # (trong đó có một singleton chức năng tiêu chuẩn cho mỗi cấu trúc dữ liệu *):

namespace System.Collections.Generic 
{ 
    public static class List 
    { 
     public static List<T> Singleton<T>(T value) => new List<T>(1) { value }; 
    } 
} 

* trừ ResizeArray tự nhiên, do đó câu hỏi này :)


Trên thực tế tôi thực tên nó Create để phù hợp với những người giúp đỡ khác tôi xác định như Tuple.Create, Lazy.Create [2], LazyTask.Create vv:

namespace System.Collections.Generic 
{ 
    static class List 
    { 
     public static List<T> Create<T>(T value) => new List<T>(1) { value }; 
    } 
} 

[2]

namespace System 
{ 
    public static class Lazy 
    { 
     public static Lazy<T> Create<T>(Func<T> factory) => new Lazy<T>(factory); 
    } 
} 
+0

Cảm ơn! Giải pháp của tôi là tốt. Vài điều: (1) việc thực hiện danh sách của bạn không được công khai, vì vậy nó không thể được sử dụng bên ngoài nhóm khai báo, và (2) mục đích của việc nhồi nhét chúng vào không gian tên System là gì? –

+0

@StephenRobinson lý do cho việc đặt phần mở rộng 'Lazy' trong' System' là 'Lazy' nằm trong' System' [và do đó 'Create' sẽ xuất hiện trong danh sách compleiton mà không có' using']. Không có gì để có được từ việc buộc mọi người phải mở một không gian tên khác? Làm cho điều khác tư nhân không phải là cố ý; cố định –

1
new[] { "item" }.ToList(); 

Đó là ngắn hơn

new List<string> { "item" }; 

và bạn không cần phải xác định loại.

3

Tuy nhiên, một cách khác, được tìm thấy trên C#/.Net Little wonders:

Enumerable.Repeat("value",1).ToList() 
+0

Khó hiểu nhưng thông minh. – PRMan

0

Hãy thử var

var s = new List<string> { "a", "bk", "ca", "d" }; 
Các vấn đề liên quan