在C#中有类似于singletonList的东西吗?

时间:2011-08-22 08:32:17

标签: c#

Java有Collections.singletonList(T),它只返回一个元素的List<T>。 C#中有类似的东西会返回IList吗?

7 个答案:

答案 0 :(得分:6)

Array实施IList;并且无法通过Add修改长度(ReadOnlytrue)。

因此,SingletonList<int>可以像以下一样轻松实现:

var slist = new int[] { 5 };

您可能希望将其包装在System.Collections.ObjectModel.ReadOnlyCollection<T>中,以便无法更改单个值(如果Java Singleton列表的工作方式如此)。 E.g。

var slist = new System.Collections.ObjectModel.ReadOnlyCollection<int>(new int[] { 5 });

您还可以创建扩展方法。

public static IList<T> AsSingletonList<T>(this IEnumerable<T> source)
{
    foreach (var item in source)
    {
        return new System.Collections.ObjectModel.ReadOnlyCollection<T>(new T[] { item });
    }
    return new System.Collections.ObjectModel.ReadOnlyCollection<T>(new T[] { default(T) });
}

或者断言源中只有一个值:

public static IList<T> AsSingletonList<T>(this IEnumerable<T> source)
{
    IList<T> result = null;
    foreach (var item in source)
    {
        if (result != null)
            throw new ArgumentOutOfRangeException("source", "Source had more than one value.");
        result = new System.Collections.ObjectModel.ReadOnlyCollection<T>(new T[] { item });
    }

    if (result == null)
        throw new ArgumentOutOfRangeException("source", "Source had no values.");
    return result;
}

编辑:使用ReadOnlyCollection<T>来防止单个值的突变。

注意:虽然我认为其他答案是正确的,但默认情况下List<T>的容量为10 - 这有点浪费。

答案 1 :(得分:5)

要回答你的问题,不。遗憾的是,没有内置任何内容,尽管在使用IEnumerable时它通常很有用。你必须自己动手。

<强>更新

这是一个实现IList<T>的高效且不可变的SingletonList的示例,而不是使用变通方法:

<强>用法

SingletonList<int> bling = new SingletonList<int>(10);    

<强>代码

public class SingletonList<T> : IList<T>
{
    private readonly T _item;

    public SingletonList(T item)
    {
        _item = item;
    }

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

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

    public void Add(T item)
    {
        throw new NotSupportedException("Add not supported.");
    }

    public void Clear()
    {
        throw new NotSupportedException("Clear not supported.");
    }

    public bool Contains(T item)
    {
        if (item == null) return _item == null;

        return item.Equals(_item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        if (array == null) throw new ArgumentNullException("array");

        array[arrayIndex] = _item;
    }

    public bool Remove(T item)
    {
        throw new NotSupportedException("Remove not supported.");
    }

    public int Count
    {
        get { return 1; }
    }

    public bool IsReadOnly
    {
        get { return true; }
    }

    public int IndexOf(T item)
    {
        return Contains(item) ? 0 : -1;
    }

    public void Insert(int index, T item)
    {
        throw new NotSupportedException("Insert not supported.");
    }

    public void RemoveAt(int index)
    {
        throw new NotSupportedException("RemoveAt not supported.");
    }

    public T this[int index]
    {
        get
        {
            if (index == 0) return _item;

            throw new IndexOutOfRangeException();
        }
        set { throw new NotSupportedException("Set not supported."); }
    }
} 

答案 2 :(得分:4)

public static class IListExtensions
{
    public static IList<T> SingletonList<T>(this IList<T> iList, T item)
    {        
        return Enumerable.Range(0, 1).Select(i => item).ToList().AsReadOnly();

        // or
        var Result = new List<T>();
        Result.Add(item);
        return Result.AsReadOnly();
    }
}

答案 3 :(得分:1)

在C#中,您可以使用包含一个元素的列表初始值设定项:

var x = new List<int> { 3 };

singletonList相反,此列表是可变的。

答案 4 :(得分:1)

对我来说这是第一次:我正在提交一个答案......我要说的不会导致自己发表评论,而是对我认为我不完全理解的问题......为了更好地理解这个问题。考虑:

    public class singletonList<T> : List<T>
    {
        public singletonList(T theValue) { base.Add(theValue); }

        public new void Add(T anotherValue) {}

        public new void AddRange(T anotherValue) {}

        public new void Clear() {}

        public new void Insert(int index, T anotherValue) {}

        public new void ToArray() {}
    }

这将创建一个新的List,其中包含只允许其值的一个实例存在于List中的任何类型的List。显然它没有完全“充实”,因为你仍然可以使用'InsertRange'和其他List更改命令。

这是一个测试,通过在声明中使用“new”来验证内部List运算符的“不可变”。

    var q = new singletonList<int>(99);
    q.Add(100);
    q.Clear();
    q.Insert(0, 788);

我怀疑这是OP想要的,但我很好奇,如果可能的话,以任何方式符合OP的规范。

尽管有ChibaCity的善意解释,我仍然完全不知道为什么人们会想要使用只包含一个元素的List。

提前感谢教育我,如果启蒙的成本是失去选票,或者面对......没问题;在我这个年纪,除了住在原地之外,我没有竞选任何事情,而且最好忘记脸部。)

答案 5 :(得分:1)

IEnumerable<T> enumerable = Enumerable.Repeat(t, 1);

使用一个元素创建IEnumerable。

答案 6 :(得分:1)

我向函数传递了一个 new[] { alreadyDeclaredVariable }。这是一种方法,只需创建一个包含 1 个元素的就地数组。