C# C语言中的不可变集合,支持(类似字符串的)方法,如;包含(IEnumerable<;T>;)“;?
C# C语言中的不可变集合,支持(类似字符串的)方法,如;包含(IEnumerable<;T>;)“;?,c#,string,collections,immutability,C#,String,Collections,Immutability,String类表示“字符的集合”,并且是不可变的。它的indexer只定义了get函数,而且它还可以,因为Char“struct”也是不可变的。所有用于操作的String方法都返回String类的新实例 我最近需要一个不可变的泛型集合,它与String(我们称之为Foo)一模一样 它应该是通用的(尽管我只将它与结构一起使用) 它应该是不可变的 它应该具有项目序列的方法,例如: IndexOf(Foo)或IndexOf(IEnumerable) StartsWith(Foo)或StartsWi
String
类表示“字符的集合”,并且是不可变的。它的indexer只定义了get函数,而且它还可以,因为Char
“struct”也是不可变的。所有用于操作的String
方法都返回String
类的新实例
我最近需要一个不可变的泛型集合,它与String
(我们称之为Foo
)一模一样
- 它应该是通用的(尽管我只将它与结构一起使用)
- 它应该是不可变的
- 它应该具有项目序列的方法,例如:
或IndexOf(Foo)
IndexOf(IEnumerable)
或StartsWith(Foo)
StartsWith(IEnumerable)
或EndsWith(Foo)
EndsWith(IEnumerable)
(带起始索引和长度,就像Take(int,int)
子字符串一样)
或Contains(Foo)
Contains(IEnumerable)
或LastIndexOf(Foo)
LastIndexOf(IEnumerable)
- 等等
Replace
method,)。我对其他选择很好奇。因为String
做了我需要的一切(不幸的是,只做了chars),感觉就像是在重新发明轮子
我需要的最简单的定义是“通用字符串”
- 在.NET中是否有类似的内容或是为.NET编写的
- 如果不是的话,一些创建一个的指导方针将是非常好的
在回答和评论后编辑: 我需要的是而不是一个包装器,它将包装指定的底层可变集合,并将其表示为只读。我需要的是一个真正不可变的
T
集合,其中包含处理T
序列的方法。想想IList.IndexOf(T)
例如,它获取项的索引。现在想想String.IndexOf(String)
方法,它(不同于String
的IndexOf(Char)
方法)得到字符序列的索引,并且String
有很多这样的方法
现在,为什么我不使用ReadOnlyCollection
:除了它不支持Contains(IEnumerable)”之类的“(类似字符串的)方法外,它还不是不可变的。例如:
var array = new char[] { 'a', 'b', 'c', 'd', 'e' };
var str = new string(array);
// array[2] is 'c' and str[2] is also 'c'
// I can't do str[2] = 'f', but:
array[2] = 'f';
// Now, array[2] is 'f' but str[2] is still 'c'
无法()更改字符串的状态。现在,让我们来看看<代码> RealDyLyCys<代码>:
var数组=newint[]{1,2,3,4,5};
var col=新的只读集合(数组);
//这里的列[2]是3
//我不能做col[2]=6,但是:
数组[2]=6;
//现在col[2]也是6。
根据请求进行编辑-我当前使用的内容: 集合(
Foo
):
//我一个小时前开始做的事情。它现在唯一能做的就是
//复制(不包装)指定的可枚举项并提供对其的只读访问。
公共密封类Foo:IList其中T:struct
{
专用只读T[]_数组;
公共T此[int索引]{get{return}数组[index];}
IList.this[int index]
{
获取{返回此[索引];}
设置{抛出新的NotSupportedException();}
}
公共食品(IEnumerable系列)
{
//方法复制指定数组的内容。
//无论“collection”发生什么情况,“\u Array”的值都将保持不变。
_Array=collection.ToArray();
}
//IList的大多数方法都是显式实现的
//返回true和导致集合抛出更改的方法
//“NotSupportedException”与ReadOnlyCollection一样。
//IEnumerable实现使用迭代器块。
}
扩展方法:
// Extensions I used to manipulate collections so far.
// These are the things I want to get rid of.
public static class FooHelpers
{
// I remove the bodies of these methods due to the confusion they have caused.
// How they work is irrelevant and I posted these because of a request.
public static bool Contains<T>(this IEnumerable<T> collection,
IList<T> pattern) { }
public static int IndexOf<T>(this IEnumerable<T> collection,
IList<T> pattern) { }
public static int LastIndexOf<T>(this IList<T> collection,
IList<T> pattern) { }
public static IEnumerable<int> IndicesOf<T>(this IEnumerable<T> collection,
IList<T> pattern) { }
public static IEnumerable<int> LastIndicesOf<T>(this IList<T> collection,
IList<T> pattern) { }
public static IEnumerable<T[]> Split(this IList<T> source,
IList<T> seperator) { }
public static bool StartsWith<T>(this IEnumerable<T> collection,
IList<T> pattern) { }
public static bool EndsWith<T>(this IList<T> collection,
IList<T> pattern) { }
public static IEnumerable<T> Take<T>(this IList<T> collection,
int startIndex,
int length) { }
public static IEnumerable<T> Take<T>(this IEnumerable<T> collection,
int startIndex,
int length) { }
public static IEnumerable<T> TakeAll<T>(this IList<T> collection,
int startIndex) { }
}
//到目前为止,我一直使用扩展来操作集合。
//这些是我想摆脱的东西。
公共静态类助手
{
//我删除了这些方法的主体,因为它们造成了混乱。
//它们是如何工作的是无关紧要的,我发布这些是因为一个请求。
公共静态布尔包含(此IEnumerable集合,
IList模式{}
公共静态int IndexOf(此IEnumerable集合,
IList模式{}
public static int LastIndexOf(此IList集合,
IList模式{}
公共静态IEnumerable指示符(此IEnumerable集合,
IList模式{}
公共静态IEnumerable lastIndicatesof(此IList集合,
IList模式{}
公共静态IEnumerable拆分(此IList源,
IList分离器{}
公共静态bool StartsWith(此IEnumerable集合,
IList模式{}
公共静态bool EndsWith(此IList集合,
IList模式{}
公共静态IEnumerable Take(此IList集合,
int startIndex,
整数长度){}
公共静态IEnumerable Take(此IEnumerable集合,
int startIndex,
整数长度){}
公共静态IEnumerable TakeAll(此IList集合,
int startIndex){}
}
我想这就是您要找的:List.AsReadOnly
只读收集?
这里似乎有两个问题: 1) 创建一个不可变的集合 简而言之,答案是否定的,没有内置的支持 最接近的答案实际上是一个
ReadOnlyCollection
,您可以创建一个简单的包装器
public class ImmutableCollection<T> : ReadOnlyCollection<T> {
public ImmutableCollection(IEnumerable<T> source) : base(source.ToList()) {}
}
如果你想找到一种有效的方法来寻找你的子序列
// Extensions I used to manipulate collections so far.
// These are the things I want to get rid of.
public static class FooHelpers
{
// I remove the bodies of these methods due to the confusion they have caused.
// How they work is irrelevant and I posted these because of a request.
public static bool Contains<T>(this IEnumerable<T> collection,
IList<T> pattern) { }
public static int IndexOf<T>(this IEnumerable<T> collection,
IList<T> pattern) { }
public static int LastIndexOf<T>(this IList<T> collection,
IList<T> pattern) { }
public static IEnumerable<int> IndicesOf<T>(this IEnumerable<T> collection,
IList<T> pattern) { }
public static IEnumerable<int> LastIndicesOf<T>(this IList<T> collection,
IList<T> pattern) { }
public static IEnumerable<T[]> Split(this IList<T> source,
IList<T> seperator) { }
public static bool StartsWith<T>(this IEnumerable<T> collection,
IList<T> pattern) { }
public static bool EndsWith<T>(this IList<T> collection,
IList<T> pattern) { }
public static IEnumerable<T> Take<T>(this IList<T> collection,
int startIndex,
int length) { }
public static IEnumerable<T> Take<T>(this IEnumerable<T> collection,
int startIndex,
int length) { }
public static IEnumerable<T> TakeAll<T>(this IList<T> collection,
int startIndex) { }
}
public class ImmutableCollection<T> : ReadOnlyCollection<T> {
public ImmutableCollection(IEnumerable<T> source) : base(source.ToList()) {}
}
public bool Contains(IEnumerable<T> pattern) {
return IndicesOf(pattern).Any();
}
public int IndexOf(IEnumerable<T> pattern) {
return IndicesOf(pattern).Select(x=>(int?)x).FirstOrDefault() ?? -1;
}
public int LastIndexOf(IEnumerable<T> pattern) {
return IndicesOf(pattern).Select(x=>(int?)x).LastOrDefault()?? -1;
}
public IEnumerable<int> IndicesOf(IEnumerable <T> pattern) {
var count=pattern.Count();
return Enumerable.Range(0,this.Count()-count).Where(i=> pattern.SequenceEqual(internalTake(i,count)));
}
public IEnumerable<int> LastIndicesOf(IEnumerable<T> pattern) {
return IndicesOf(pattern).Reverse(); // Could Optimize
}
private IEnumerable<IEnumerable<T>> internalSplit(IEnumerable<T> seperator) {
var splitPoints=this.IndicesOf(seperator);
var length=seperator.Count();
var lastCount=0;
foreach(var point in splitPoints.Where(x=>!splitPoints.Any(y=>y<x && y+length>x))) {
yield return this.Take(lastCount,point-lastCount);
lastCount=point+length;
}
yield return this.TakeAll(lastCount);
}
public ImmutableCollection<T>[] Split(IEnumerable<T> seperator) {
return internalSplit(seperator).Select(x=>new ImmutableCollection<T>(x)).ToArray();
}
public bool StartsWith(IEnumerable<T> pattern) {
return pattern.SequenceEqual(this.Take(pattern.Count()));
}
public bool EndsWith(IEnumerable<T> pattern) {
return pattern.SequenceEqual(this.Skip(this.Count()-pattern.Count()));
}
private IEnumerable<T> internalTake(int startIndex, int length) {
var max=(length==-1) ? this.Count() : Math.Min(this.Count(),startIndex+length);
for (int i=startIndex;i<max;i++) yield return this[i];
}
public ImmutableCollection<T> Take(int startIndex, int length) {
return new ImmutableCollection<T>(internalTake(startIndex,length));
}
public ImmutableCollection<T> TakeAll(int startIndex) {
return new ImmutableCollection<T>(internalTake(startIndex,-1));
}