c#中有类似singletonList的东西吗?

本文关键字:singletonList | 更新日期: 2023-09-27 18:06:12

Java的Collections.singletonList(T)只返回一个元素的List<T>。c#中是否有类似的东西返回IList ?

c#中有类似singletonList的东西吗?

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

创建一个只有一个元素的IEnumerable

Array实现IList;不能通过Add修改长度(因为ReadOnlytrue)。

因此,SingletonList<int>可以很容易地实现为:

var slist = new int[] { 5 };

你可能想把它包装在System.Collections.ObjectModel.ReadOnlyCollection<T>中,这样单个值就不能被改变了(如果Java Singleton列表是这样工作的)。例如

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

Edit:使用ReadOnlyCollection<T>来防止单个值的变异。

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

回答你的问题,没有。遗憾的是,虽然它在使用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."); }
    }
} 
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();
    }
}

在c#中,你可以使用一个元素的列表初始化器:

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

singletonList相反,此列表是可变的。如果你想要一些不可变的东西,你可以对结果对象调用AsReadOnly():

// Looks strange, but, yes, this is actually valid C#.
var x = new List<int> { 3 }.AsReadOnly();

我传递了一个new[] { alreadyDeclaredVariable }到函数中。这是一种方法,创建一个包含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中存在一个value-Type的实例。显然,它并没有完全"充实",因为你仍然可以使用"InsertRange"和其他列表更改命令。

下面是一个测试,用于验证内部List操作符的"不可变",因为它们在声明中使用了"new"。

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

我怀疑这是OP想要的,但我很好奇这是否可能在任何方面符合OP的规范。

尽管ChibaCity给出了友好的解释,但我仍然完全不明白为什么要使用只包含一个元素的List。

提前感谢你对我的教育,如果启蒙的代价是失去选票,还是面子…没有问题;在我这个年纪,除了呆在原地,我什么都不跑,脸最好忘记:)