String
クラスは「文字のコレクション」を表し、不変です。インデクサーにはget関数のみが定義されており、Char
「struct」も不変であるため問題ありません。操作に使用されるすべてのメソッドは、クラスString
の新しいインスタンスを返します。String
私は最近、まったく同じような不変のジェネリックコレクションが必要でしたString
(それを呼びましょうFoo<T>
)。
- 汎用である必要があります(ただし、構造体でのみ使用します)。
- 不変である必要があります。
- アイテム
のシーケンスのメソッドが必要です。次に例を示します。
IndexOf(Foo<T>)
またIndexOf(IEnumerable<T>)
StartsWith(Foo<T>)
またStartsWith(IEnumerable<T>)
EndsWith(Foo<T>)
またEndsWith(IEnumerable<T>)
Take(int, int)
(開始インデックスと長さを使用して、と同じようにSubstring
)Contains(Foo<T>)
またContains(IEnumerable<T>)
LastIndexOf(Foo<T>)
またLastIndexOf(IEnumerable<T>)
- 等
アイテムへの読み取り専用アクセス用の不変クラスを作成し、Stringの機能を模倣する拡張メソッドをいくつか作成しましたが、実装の効率については本当に疑問があります(実際にReplace
メソッドを要求しました)。代替案に興味があります。私が必要とするすべてのことを(残念ながら、charsだけに)行うのでString
、それは車輪の再発明のように感じます。
私が必要とするものの最も簡単な定義は「一般的な文字列」です。
- .NETにこのようなものや.NET用に書かれたものはありますか?
- そうでない場合は、それを作成するためのいくつかのガイドラインが素晴らしいでしょう。
回答とコメントの後に編集します。
私が必要としているのは、指定された基になる可変コレクションをラップし、それを読み取り専用として表すラッパーではありません。私が必要としているのは、のシーケンスを処理するためのメソッドを備えた真に不変のコレクションです。たとえば、アイテムのインデックスを取得するとします。ここでメソッドを考えてみましょう。(のメソッドとは異なり)文字のシーケンスのインデックスを取得し、これらの種類のメソッドを多数備えています。T
T
IList<T>.IndexOf(T)
String.IndexOf(String)
IndexOf(Char)
String
String
さて、私が使用しない理由:「 Contains(IEnumerable)」などの(文字列のような)メソッドをReadOnlyCollection<T>
サポートしていないことを除けば、不変でもありません。例:
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'
文字列の状態を変更する方法はありません(これはハックではありません)。それでは、見てみましょうReadOnlyCollection<T>
:
var array = new int[] { 1, 2, 3, 4, 5 };
var col = new ReadOnlyCollection<int>(array);
// Here the col[2] is 3
// I can't do col[2] = 6, but:
array[2] = 6;
// Now the col[2] is 6 as well.
リクエストに応じて編集-私が現在使用しているもの:
コレクション(Foo<T>
):
// Something I started like an hour ago. The only thing it does right now is to
// copy (not wrap) a specified enumerable and provide read-only access to it.
public sealed class Foo<T> : IList<T> where T: struct
{
private readonly T[] _Array;
public T this[int index] { get { return _Array[index]; } }
IList<T>.this[int index]
{
get { return this[index]; }
set { throw new NotSupportedException(); }
}
public Foo(IEnumerable<T> collection)
{
// Enumerable.ToArray() method copies the content of the specified array.
// Whetever happens to the "collection", value of "_Array" will stay the same.
_Array = collection.ToArray();
}
// Most of the methods of IList<T> are explicitly implemented. IsReadOnly
// returns true and the methods that cause a change in collection throw
// "NotSupportedException"s just like ReadOnlyCollection<T>.
// IEnumerable<T> implementation uses an iterator block.
}
拡張メソッド:
// 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) { }
}