Java有Collections.singletonList(T)
,它返回一个仅包含一个元素的List<T>
。在C#中是否有类似的方法可以返回IList
?
Java有Collections.singletonList(T)
,它返回一个仅包含一个元素的List<T>
。在C#中是否有类似的方法可以返回IList
?
IEnumerable<T> enumerable = Enumerable.Repeat(t, 1);
使用一个元素创建IEnumerable。
Array
实现了 IList
接口;且由于 ReadOnly
为 true
,因此无法通过 Add
修改其长度。
因此,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;
}
编辑:使用 ReadOnlyCollection<T>
防止单个值的变异。
注意:虽然我认为其他答案是正确的,但默认情况下,List<T>
的容量为10,这有点浪费空间。
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();
}
}
AsReadOnly()
并且它是不可变的。所以:return Enumerable.Range(0, 1).Select(i => item).ToList().AsReadOnly()
- ZoolWayvar 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() {}
}
这将创建一个新的列表,其中仅允许存在其值类型的一个实例。显然它还没有完全“充实”,因为您仍然可以使用“InsertRange”和其他列表更改命令。
这里有一个测试,验证了它对于由于在声明中使用“new”而被屏蔽的内部列表运算符是“不可变”的。
var q = new singletonList<int>(99);
q.Add(100);
q.Clear();
q.Insert(0, 788);
我怀疑这不是OP所想要的,但我很好奇这是否在任何方面满足了OP的规格。
尽管ChibaCity友好的解释,我仍然完全不明白为什么有人会想使用只包含一个元素的列表。
提前感谢您对我的教育,如果启示成本是失去票数或面子......没问题;在我这个年纪,我除了待在原地,再也不会去做其他任何事情,而且最好忘记面子 :)。