vector<T>
のC++でresize(int newsize)
を使用する場合、これは、このsize
のvector
がnewsize
に設定され、インデックスが[0..newsize)
の範囲で実行されることを意味します。 List<T>
のC#で同じことを行うには?List<T>
プロパティCapacity
を変更すると、Capacity
のみが変更されますが、Count
は同じままです。さらに、インデックスは[0..Count)
の範囲にあります。手伝ってください。
追伸vector<T> tmp
にtmp.size() == 5
が付いていると想像してください。tmp[9]
を参照することはできませんが、tmp.resize(10)
を使用するとtmp[9]
を参照することがあります。 C#では、List<T> tmp
とtmp.Count == 5
がある場合、tmp[9]
(IndexOutOfRangeException
)を参照できませんが、tmp.Capacity=10
を設定しても、tmp[9]
を参照できませんtmp.Count
のcozは5のままです。類似点を見つけたいC#でのサイズ変更。
いいえ。ただし、拡張メソッドを使用して独自のメソッドを追加できます。以下はstd::vector<T>::resize()
と同じ動作で、同じ時間の複雑さを含みます。唯一の違いは、C++ではvoid resize ( size_type sz, T c = T() )
を使用してデフォルトを定義できることと、テンプレートの動作方法は、アクセス可能なパラメーターなしのコンストラクターがないT
のデフォルトなしでそれを呼び出す場合に問題ないことです。 。 C#ではそれを行うことができないため、代わりに、デフォルトで使用されていないケースと一致する制約のないメソッドと、それを呼び出すwhere new()
制約のあるメソッドを作成する必要があります。
_public static class ListExtra
{
public static void Resize<T>(this List<T> list, int sz, T c)
{
int cur = list.Count;
if(sz < cur)
list.RemoveRange(sz, cur - sz);
else if(sz > cur)
{
if(sz > list.Capacity)//this bit is purely an optimisation, to avoid multiple automatic capacity changes.
list.Capacity = sz;
list.AddRange(Enumerable.Repeat(c, sz - cur));
}
}
public static void Resize<T>(this List<T> list, int sz) where T : new()
{
Resize(list, sz, new T());
}
}
_
これで、myList.Resize(23)
またはmyList.Resize(23, myDefaultValue)
のようなものが、C++のベクトルから期待されるものと一致します。ただし、C++ではポインターのベクトルが存在する場合があるのに、C#では参照型のリストが存在することに注意してください。したがって、C++のT()
がnullポインターを生成する場合(ポインターであるため)、ここではパラメーターのないコンストラクターを呼び出すと想定しています。そのため、2番目のメソッドを次のように置き換えるのに慣れている動作に近いことがわかるでしょう。
_ public static void Resize<T>(this List<T> list, int sz)
{
Resize(list, sz, default(T));
}
_
これは値の型(パラメーターなしのコンストラクターを呼び出す)と同じ効果がありますが、参照型ではnullで埋められます。この場合、クラス全体を次のように書き換えることができます。
_public static class ListExtra
{
public static void Resize<T>(this List<T> list, int sz, T c = default(T))
{
int cur = list.Count;
if(sz < cur)
list.RemoveRange(sz, cur - sz);
else if(sz > cur)
list.AddRange(Enumerable.Repeat(c, sz - cur));
}
}
_
これは_std::vector<T>
_と_List<T>
_の違いについてではなく、C++とC#でのポインターの使用方法の違いについてであることに注意してください。
ちょうど Jon Hannaの答え をもっと読みやすくするために:
public static class ListExtras
{
// list: List<T> to resize
// size: desired new size
// element: default value to insert
public static void Resize<T>(this List<T> list, int size, T element = default(T))
{
int count = list.Count;
if (size < count)
{
list.RemoveRange(size, count - size);
}
else if (size > count)
{
if (size > list.Capacity) // Optimization
list.Capacity = size;
list.AddRange(Enumerable.Repeat(element, size - count));
}
}
}
ごめんなさい。これは何が必要ですか? List.TrimExcess()
_List<T>.Capacity
_の設定は、std::vector<T>.reserve(..)
の使用に似ています。多分List<T>.AddRange(..)
はあなたのニーズに合うでしょう。
これが私の解決策です。
_private void listResize<T>(List<T> list, int size)
{
if (size > list.Count)
while (size - list.Count > 0)
list.Add(default<T>);
else if (size < list.Count)
while (list.Count - size > 0)
list.RemoveAt(list.Count-1);
}
_
size
と_list.Count
_が同じ場合、リストのサイズを変更する必要はありません。
default(T)
パラメータは、null
、_""
_、_0
_または他のnull許容型の代わりに使用され、リストの空の項目を埋めます。 _<T>
_のタイプを知っている(参照、値、構造体など)。
追伸
for
ループの代わりにwhile
ループを使用したところ、問題が発生しました。リストのサイズが常に私が求めていたものであるとは限りませんでした。それは小さかったです。なぜだと思いますか?確認してください:
_private void listResize<T>(List<T> list, int size) { if (size > list.Count) for (int i = 0; i <= size - list.Count; i++) list.Add(default(T)); else if (size < list.Count) for (int i = 0; i <= list.Count - size; i++) list.RemoveAt(list.Count-1); }
_