C#で単一のアイテムリストを作成するためのショートカット


134

C#には、List <T>を1つのアイテムのみでインスタンス化するインラインショートカットがあります。

私は現在やっています:

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

どこにでもこのコードがあると、読みやすさが低下します。私はこのようなユーティリティメソッドを使うことを考えました:

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

だから私はできる:

SingleItemList("title");

より短く/よりきれいな方法はありますか?

ありがとう。

回答:


245

単にこれを使用してください:

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

()括弧も省略できます:

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

更新:もちろん、これは複数のエントリでも機能します。

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

5
最初のオプションの括弧に1リテラルを入れて、デフォルトの10ではなく1つのスペースのストレージが割り当てられるようにする
Joel Coehoorn

5
デフォルトは4になります。新しいList <string> {"Hello"} .Capacity == 4
Jon Skeet

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

他のユーザーが投稿したものと非常に似ていますが、最初は単一のアイテムにのみスペースを割り当てることが保証されます。

もちろん、後でたくさんのものを追加することがわかっている場合は、良いアイデアではないかもしれませんが、一度言及する価値はあります。


容量は1に設定されています。このページでジョンスキートの両方を含む4つの回答に投票しましたが、これが最も正しいと思います。
Lonely Coder

28

拡張メソッドを使用するというマイケルのアイデアは、さらに単純なものにつながります。

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

だからこれを行うことができます:

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

気に入ったかどうかわかりませんが、気にしてください...


1
また、私はそれが好きかどうかもわかりません。これは(たとえば)文字列型の「奇妙な」拡張ではありませんか?
M4N 2009年

1
私はあなたの本の拡張メソッドにまだ到達していません、ジョン:-)これはちょっと奇妙に思われますが、私はそれのユーティリティが好きです。マーティンとジョンに感謝します。
ライアンイッ

2
@Martin:あらゆるタイプの奇妙な拡張です。これは一般的には推奨されませんが、興味深い一般的な考え方です。
Jon Skeet、

4
これには、特に値の型に関して、内部ドメイン固有の言語が使用されています。例を見てみましょう:clock.AlertUser.In(1.Minute)は、clock.AlertUser(TimeSpan.FromMinutes(1));よりもはるかに優れています。
マイケルメドウズ

17

Google Javaコレクションへの露出に基づいた、以前の私の答えとは異なる答え:

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

次に:

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

私はGJCをチェックすることをお勧めします-興味深いものをたくさん持っています。(個人的には「アルファ」タグは無視します-「アルファ」であるのはオープンソースバージョンのみであり、非常に安定しており、頻繁に使用される内部APIに基づいています。)



7

メソッドチェーンで拡張メソッドを使用します。

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

これはあなたにこれをさせるでしょう:

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

または

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

更新

リスト初期化子を使用できるようになりました。

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

http://msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspxを参照してください


多分これは2009年以降のC#の新しいバージョンが原因であるかもしれませんが、私はnew List<string> {"Yes"}より良いと思います...?
ErikE 2014

@ErikE Microsoftのドキュメント(msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx)によると、これはVisual Studio 2008でサポートされていました。その時私はこれを過度に複雑にした。更新しています。
Michael Meadows 14


4

Javaで列挙可能な単一のアイテムの場合は、Collections.singleton( "string");になります。

C#では、これは新しいリストよりも効率的です:

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;
    }
}

しかし、フレームワークを使用するより簡単な方法はありますか?


それは私の意見では実際には最良の答えです。割り当てサイズを減らすために、単一のアイテムリストを持つことは非常に一般的なパターンです。すでにショートカットを探しているのなら、便利なものと良いものを組み合わせるのもよいでしょう。
アレックス


2

私はこの小さな機能を持っています:

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

具体的な戻り値の型を規定していないため、これは非常に一般的であり、私はそれをいたるところで使用しています。あなたのコードは次のようになります

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

しかしもちろん、

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

LINQステートメントの出力に1つのアイテムを追加または追加する必要があるときに、私はよくそれを使用します。たとえば、選択リストに空白のアイテムを追加するには、次のようにします。

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

少し節約 ToList()を、Addステートメントをます。

(遅い答えですが、私はこの古い人に偶然出会い、これが役立つかもしれないと思いました)



2

他の答えに触発され(そして、必要なときにいつでもそれを手に入れることができます!)、F#(singletonデータ構造ごとに標準関数を持っています*)に合わせて名前/スタイルを調整します。

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

* ResizeArrayもちろんそれ自体を除いて、この質問:)


実際にCreate私が定義する他のヘルパーTuple.CreateLazy.Create[2] など)に合わせて実際に名前を付けていますLazyTask.Create

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);
    }
}

ありがとう!私の解決策も。カップルの事柄:(1)リストの実装はパブリックではないため、宣言アセンブリの外では使用できません。(2)これらをSystem名前空間に詰め込む目的は何ですか?
Codure 2017

置くための@StephenRobinsonの理由Lazyで拡張子はSystemということですLazy、それ自体がであるSystem[ひいてはCreateなしcompleitonリストに表示されますusing]。人々をopendiff名前空間に強制することから得られるものは何ですか?他のものをプライベートにすることは意図的ではありませんでした。修正済み
Ruben Bartelink 2017

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.