Phím tắt để tạo danh sách mục đơn trong C #


134

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.

Tôi hiện đang làm:

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

Có mã này ở khắp mọi nơi làm giảm khả năng đọc. Tôi đã nghĩ đến việc sử dụng một phương pháp tiện í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ó cách nào ngắn hơn / sạch hơn không?

Cảm ơn.

Câu trả lời:


245

Đơ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 dấu ngoặc ():

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

Cập nhật: tất nhiên điều này cũng hoạt động cho nhiều mục:

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

5
đặt 1 chữ trong ngoặc đơn của tùy chọn đầu tiên, để lưu trữ cho chính xác một không gian được phân bổ thay vì 10 mặc định
Joel Coehoorn

5
Mặc định kết thúc là 4, tôi tin rằng: Danh sách mới <chuỗi> {"Xin chào"} .Capacity == 4
Jon Skeet

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

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

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


Công suất được đặt thành một. Tôi đã bỏ phiếu cho bốn câu trả lời trên trang này bao gồm cả hai câu trả lời của Jon Skeet nhưng tôi cho rằng câu trả lời này là đúng nhất.
Bộ giải mã cô đơn

28

Ý tưởng của Michael về việc sử dụng các phương pháp mở rộng dẫn đến một thứ thậm chí còn đơn giản hơn:

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

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

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

Tôi không chắc là tôi có thích hay không, phiền bạn ...


1
Tôi cũng không chắc là mình thích nó: đây không phải là một phần mở rộng "lạ" của loại chuỗi (chẳng hạn)?
M4N

1
Tôi chưa thực hiện được các phương pháp mở rộng trong cuốn 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.
Ryan Ische

2
@Martin: Đây 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ị.
Jon Skeet

4
Nó có một số ngôn ngữ sử dụng tên miền cụ thể nội bộ, đặc biệt là với các loại giá trị. Lấy ví dụ: clock.AlertUser.In (1.Minute) đọc tốt hơn nhiều so với clock.AlertUser (TimeSpan.FromMinutes (1));
Michael Meadows

17

Một câu trả lời khác cho câu hỏi trước đó của tôi, dựa trên việc tiếp xúc với Bộ sưu tập Google Java :

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 bạn nên kiểm tra GJC - nó có rất nhiều nội dung thú vị. (Cá nhân tôi bỏ qua thẻ "alpha" - đây chỉ là phiên bản nguồn mở là "alpha" và nó dựa trên API nội bộ rất ổn định và được sử dụng nhiều .)



7

Sử dụng một phương thức mở rộng với chuỗi phương thức.

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

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

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

hoặc là

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 khởi tạo:

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

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


Có lẽ điều này là do các phiên bản C # mới hơn kể từ năm 2009, nhưng tôi thấy new List<string> {"Yes"}tốt hơn ...?
ErikE

@ErikE Theo tài liệu của Microsoft ( msdn.microsoft.com/en-us/l Library / bb384062 (v = vs.90) .aspx ) điều này đã được hỗ trợ trong Visual Studio 2008. Tôi quá phức tạp điều này vào thời điểm đó. Đang cập nhật.
Michael Meadows

7

Còn một cách khác, được tìm thấy trên "C # /. Net Little wonderers" (thật không may, trang web không còn tồn tại nữa):

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

Nhầm lẫn nhưng thông minh.
PRman

4

Đối với một mục duy nhất có thể đếm được trong java, đó sẽ là Collections.singleton ("chuỗi");

Trong c #, điều này sẽ hiệu quả hơn 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 có một cách đơn giản hơn bằng cách sử dụng khung?


Đó thực sự là câu trả lời tốt nhất theo ý kiến ​​của tôi. Đó là một mẫu rất phổ biến để có một danh sách mục duy nhất, để giảm kích thước phân bổ. Nếu bạn đang tìm kiếm một phím tắt, bạn cũng có thể kết hợp thuận tiện với tốt.
Alex


2

Tôi đã có chức năng nhỏ này:

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

Vì nó không quy định loại trả lại cụ thể nên nó rất chung chung nên tôi sử dụng nó ở mọi nơi. Mã của bạn sẽ trông như thế nào

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ó khi tôi phải nối / thêm một mục vào đầu ra của câu lệnh LINQ. Ví dụ để thêm một mục trống vào danh sách lựa chọn:

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

Lưu một vài ToList()Addbáo cáo.

(Câu trả lời muộn, nhưng tôi tình cờ thấy ông già này và nghĩ rằng điều này có thể hữu ích)



2

Lấy cảm hứng từ các câu trả lời khác (và vì vậy tôi có thể chọn nó bất cứ khi nào tôi cần!), Nhưng với cách đặt tên / kiểu được căn chỉnh với F # (có singletonchứ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 };
    }
}

* ngoại trừ ResizeArraychính nó, tất nhiên, vì vậy câu hỏi này :)


Trong thực tế, tôi thực sự đặt tên cho nó Createđể phù hợp với những người trợ giúp khác mà tôi xác định, chẳng hạn như Tuple.Create, Lazy.Create[2], LazyTask.Createv.v .:

namespace System.Collections.Generic
{
    public 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);
    }
}

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ông khai, vì vậy nó không thể được sử dụng bên ngoài tổ hợp khai báo và (2) mục đích của việc đưa chúng vào không gian tên Hệ thống là gì?
Codure

@StephenRobinson lý do để đưa Lazyphần mở rộng vào SystemLazychính nó nằm trong System[và do đó Createsẽ xuất hiện trong danh sách compleiton mà không có using]. Không có gì có thể đạt được từ việc buộc mọi người vào openmột không gian tên khác? Làm cho điều khác riêng tư không phải là cố ý; đã sửa
Ruben Bartelink

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.