web-dev-qa-db-ja.com

C#でRedim Preserve?

今日、C#が動的なサイズの配列をサポートしていないことを知ってショックを受けました。それでは、C#で VB.NET 開発者が ReDim Preserve を使用してこれに対処する方法を教えてください。

関数の最初では、配列の上限がわかりません。これは、データベースから返される行に依存します。

37
JL.

代わりにArrayListsまたはGenericsを使用してください

11
Michael L

VB.NETには、動的にサイズ設定される配列の概念もありません-CLRはそれをサポートしていません。

「Redim Preserve」に相当するのは Array.Resize<T> -ただし、mustは、元の配列への他の参照がある場合、それらはまったく変更されないことに注意してください。例えば:

using System;

class Foo
{
    static void Main()
    {
        string[] x = new string[10];
        string[] y = x;

        Array.Resize(ref x, 20);
        Console.WriteLine(x.Length); // Prints out 20
        Console.WriteLine(y.Length); // Still prints out 10
    }
}

これがRedim Preserveと同等であることの証明:

Imports System

Class Foo
    Shared Sub Main()
        Dim x(9) as String
        Dim y as String() = x

        Redim Preserve x(19)
        Console.WriteLine(x.Length)
        Console.WriteLine(y.Length)
    End Sub
End Class

2つのプログラムは同等です。

動的なサイズのコレクションが本当に必要な場合は、List<T>(または同様のもの)。配列を直接使用することにはさまざまな問題があります-詳細については、 Eric Lippertのブログ投稿 を参照してください。だからといって、常にそれらを避けるべきだというわけではありません-しかし、あなたはあなたが何を扱っているかを知る必要があります。

74
Jon Skeet

List <T>を使用します。必要に応じて動的にサイズが調整されます。

10
driis

あなたは本当にReDimを使うべきではありません、それはすべて高価になる可能性があります。 List(Of T)が好きですが、この領域には多くのオプションがあります。

とはいえ、質問がありましたが、ここに答えがあります。

x = (int[]) Utils.CopyArray((Array) x, new int[10]);
4
Jonathan Allen

上記の回答のnoneが多次元配列の概念に近づいていることに気づかずにはいられませんでした。そうは言っても、ここに例があります。問題の配列は、xとして事前定義されています。

int[,] temp = new int[newRows, newCols];
int minRows = Math.Min(newRows, x.GetUpperBound(0) + 1);
int minCols = Math.Min(newCols, x.GetUpperBound(1) + 1);
for (int i = 0; i < minRows ; ++i)
     for (int j = 0; j < minCols; ++j)
         temp[i, j] = x[i, j];
x = temp;
2
Hameer Abbasi

ただの楽しみのために、一次元配列を再拡張/拡張するためにジェネリックを使用する1つの方法があります(もう1つの「行」を追加します)。

static T[] Redim<T>(T[] arr, bool preserved)
{
    int arrLength = arr.Length;
    T[] arrRedimed = new T[arrLength + 1];
    if (preserved)
    {
        for (int i = 0; i < arrLength; i++)
        {
            arrRedimed[i] = arr[i];
        }
    }
    return arrRedimed;
}

そして、n行を追加するもの(これは、ユーザーが配列を小さくすることを妨げませんが、forループでエラーをスローします):

static T[] Redim<T>(T[] arr, bool preserved, int nbRows)
{
    T[] arrRedimed = new T[nbRows];
    if (preserved)
    {
        for (int i = 0; i < arr.Length; i++)
        {
            arrRedimed[i] = arr[i];
        }
    }
    return arrRedimed;
}

私はあなたがそのアイデアを得ると確信しています。

多次元配列(2次元)の場合、1つの可能性があります。

static T[,] Redim<T>(T[,] arr, bool preserved)
{
    int Ubound0 = arr.GetUpperBound(0);
    int Ubound1 = arr.GetUpperBound(1);
    T[,] arrRedimed = new T[Ubound0 + 1, Ubound1];
    if (preserved)
    {
        for (int j = 0; j < Ubound1; j++)
        {
            for (int i = 0; i < Ubound0; i++)
            {
                arrRedimed[i, j] = arr[i, j];
            }
        }
    }
    return arrRedimed;
}

プログラムで、指定されたタイプの有無にかかわらずこれを使用すると、コンパイラはそれを認識します:

int[] myArr = new int[10];
myArr = Redim<int>(myArr, true);

または

int[] myArr = new int[10];
myArr = Redim(myArr, true);

しかし、これらすべてが本当に関連性があるかどうかはわかりません。 = D私を修正するか、コードを改善してください。 ;)

2
Tete1805

それはずっと前ですが、簡単な解決策を探している人を助けるかもしれません-私は別のフォーラムで素晴らしいものを見つけました:

//from Applied Microsoft.NET framework Programming - Jeffrey Richter
public static Array RedimPreserve(Array origArray, Int32 desiredSize)
        {
            System.Type t = origArray.GetType().GetElementType();
            Array newArray = Array.CreateInstance(t, desiredSize);
            Array.Copy(origArray, 0, newArray, 0, Math.Min(origArray.Length, desiredSize));
            return newArray;
        }

ソース: https://social.msdn.Microsoft.com/Forums/en-US/6759816b-d525-4752-a3c8-9eb5f4a5b194/redim-in-c?forum=csharplanguage

1
AllDayPiano