在C#中有类似于singletonList的东西吗?
Java有Collections.singletonList(T)
,它返回恰好一个元素的List
。 在C#中有类似的东西返回IList
吗?
要回答你的问题,不。 遗憾的是,没有内置任何内容,尽管在使用IEnumerable时它通常很有用。 你必须自己动手。
更新
这里是一个实现IList
的高效且不可变的SingletonList的示例,而不是使用变通方法:
用法
SingletonList bling = new SingletonList (10);
码
public class SingletonList : IList { private readonly T _item; public SingletonList(T item) { _item = item; } public IEnumerator 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."); } } }
Array
实现IList
; 并且无法通过Add
修改长度(因为ReadOnly
为true
)。
因此, SingletonList
可以像以下一样轻松实现:
var slist = new int[] { 5 };
您可能希望将其包装在System.Collections.ObjectModel.ReadOnlyCollection
以便无法更改单个值(如果Java Singleton列表的工作方式如此)。 例如
var slist = new System.Collections.ObjectModel.ReadOnlyCollection(new int[] { 5 });
您还可以创建扩展方法。
public static IList AsSingletonList (this IEnumerable source) { foreach (var item in source) { return new System.Collections.ObjectModel.ReadOnlyCollection (new T[] { item }); } return new System.Collections.ObjectModel.ReadOnlyCollection (new T[] { default(T) }); }
或者断言在源中只有一个值:
public static IList AsSingletonList (this IEnumerable source) { IList 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 (new T[] { item }); } if (result == null) throw new ArgumentOutOfRangeException("source", "Source had no values."); return result; }
编辑 :使用ReadOnlyCollection
来防止单个值的突变。
注意 :虽然我认为其他答案是正确的,但默认情况下List
的容量为10 – 这有点浪费。
public static class IListExtensions { public static IList SingletonList (this IList iList, T item) { return Enumerable.Range(0, 1).Select(i => item).ToList().AsReadOnly(); // or var Result = new List (); Result.Add(item); return Result.AsReadOnly(); } }
在C#中,您可以使用包含一个元素的列表初始值设定项:
var x = new List { 3 };
与singletonList
相反,此列表是可变的。
这对我来说是第一次:我正在提交一个答案……我要说的不是引导自己发表评论,而是对我认为我不完全理解的问题……为了更好明白这个问题。 考虑:
public class singletonList : List { 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(99); q.Add(100); q.Clear(); q.Insert(0, 788);
我怀疑这是OP想要的,但我很好奇,如果可能的话,以任何方式满足OP的规范。
尽管ChibaCity的解释如此,但我仍然完全不知道为什么人们会想要使用仅包含一个元素的List。
提前感谢教育我,如果启蒙的成本是失去选票,或者面对……没问题; 在我这个年纪,除了呆在原地,我没有竞选任何东西,脸最好忘了:)
IEnumerable
使用一个元素创建IEnumerable。