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)
    • 等等
我创建了一个以只读方式访问其项的不可变类,并编写了一些扩展方法来模拟String的功能,但我确实对实现的效率有怀疑(实际上我要求使用
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));
 }