28

我还是 C# 的新手,我一直在努力解决数组上的各种问题。我有一组元数据对象(名称值对),我想知道如何只创建我真正需要的“InputProperty”对象的数量。在这个循环中,我将元素的数量任意设置为 20,并尝试在条目变为 null 时退出,但接收端的 Web 服务不喜欢传递给它的任何 null 元素:

private Update BuildMetaData(MetaData[] nvPairs)
{
    Update update = new Update();
    InputProperty[] ip = new InputProperty[20];  // how to make this "dynamic"
    int i;
    for (i = 0; i < nvPairs.Length; i++)
    {
        if (nvPairs[i] == null) break;
        ip[i] = new InputProperty();
        ip[i].Name = "udf:" + nvPairs[i].Name;
        ip[i].Val = nvPairs[i].Value;
    }
    update.Items = ip;
    return update;
}

总之,假设我在上面的输入数组中只有 3 个名称值对?与其为名为 ip 的数组分配 20 个元素,不如对其进行编码,以使 ip 仅与需要的一样大。更新对象通过另一个 web 服务传递,因此序列化很重要(即我不能使用 namevaluecollection 等)。

ps 是通过“添加评论”工具跟进已发布问题的唯一方法吗?

4

9 回答 9

30
InputProperty[] ip = new InputProperty[nvPairs.Length]; 

或者,您可以使用如下列表:

List<InputProperty> list = new List<InputProperty>();
InputProperty ip = new (..);
list.Add(ip);
update.items = list.ToArray();

我想指出的另一件事是,在 C# 中,您可以在循环内部的 for 循环中删除 int 变量的使用:

for(int i = 0; i<nvPairs.Length;i++
{
.
.
}

只是因为我有心情,这是一种更清洁的方法来执行此方法 IMO:

private Update BuildMetaData(MetaData[] nvPairs)
{
        Update update = new Update();
        var ip = new List<InputProperty>();

        foreach(var nvPair in nvPairs)
        {
            if (nvPair == null) break;
            var inputProp = new InputProperty
            {
               Name = "udf:" + nvPair.Name,
               Val = nvPair.Value
            };
            ip.Add(inputProp);
        }
        update.Items = ip.ToArray();
        return update;
}
于 2009-03-25T19:30:08.313 回答
24

如果您不想使用List,ArrayList或其他动态大小的集合然后转换为数组(顺便说一下,这是我推荐的方法),那么您必须将数组分配到可能的最大值大小,跟踪您放入其中的项目数量,然后创建一个仅包含这些项目的新数组:

private Update BuildMetaData(MetaData[] nvPairs)
{
    Update update = new Update();
    InputProperty[] ip = new InputProperty[20];  // how to make this "dynamic"
    int i;
    for (i = 0; i < nvPairs.Length; i++)
    {
        if (nvPairs[i] == null) break;
        ip[i] = new InputProperty(); 
        ip[i].Name = "udf:" + nvPairs[i].Name;
        ip[i].Val = nvPairs[i].Value;
    }
    if (i < nvPairs.Length)
    {
        // Create new, smaller, array to hold the items we processed.
        update.Items = new InputProperty[i];
        Array.Copy(ip, update.Items, i);
    }
    else
    {
        update.Items = ip;
    }
    return update;
}

另一种方法是始终分配update.Items = ip;,然后在必要时调整大小:

update.Items = ip;
if (i < nvPairs.Length)
{
    Array.Resize(update.Items, i);
}

它的代码更少,但最终可能会完成相同数量的工作(即创建一个新数组并复制旧项目)。

于 2009-03-25T19:53:55.260 回答
8

用这个:

 Array.Resize(ref myArr, myArr.Length + 5);
于 2012-08-08T12:41:13.850 回答
5

是否需要是一个数组?如果您使用 ArrayList 或 C# 中可用的其他对象之一,则内容不会受到此限制。Hashtable、IDictionnary、IList 等都允许动态数量的元素。

于 2009-03-25T19:31:22.117 回答
2

您可以在方法中使用 List 并在最后将其转换为数组。但我认为如果我们谈论 20 的最大值,您的代码会更快。

    private Update BuildMetaData(MetaData[] nvPairs)
    {
        Update update = new Update();
        List<InputProperty> ip = new List<InputProperty>();
        for (int i = 0; i < nvPairs.Length; i++)
        {
            if (nvPairs[i] == null) break;
            ip[i] = new InputProperty();
            ip[i].Name = "udf:" + nvPairs[i].Name;
            ip[i].Val = nvPairs[i].Value;
        }
        update.Items = ip.ToArray();
        return update;
    }
于 2009-03-25T19:34:23.933 回答
2

或者在 C# 3.0 中使用System.Linq你可以跳过中间列表:

private Update BuildMetaData(MetaData[] nvPairs)
{
        Update update = new Update();
        var ip = from nv in nvPairs
                 select new InputProperty()
                 {
                     Name = "udf:" + nv.Name,
                     Val = nv.Value
                 };
        update.Items = ip.ToArray();
        return update;
}
于 2009-03-25T19:40:10.847 回答
2

用于Array.CreateInstance动态创建数组。

    private Update BuildMetaData(MetaData[] nvPairs)
    {
        Update update = new Update();
        InputProperty[] ip = Array.CreateInstance(typeof(InputProperty), nvPairs.Count()) as InputProperty[];
        int i;
        for (i = 0; i < nvPairs.Length; i++)
        {
            if (nvPairs[i] == null) break;
            ip[i] = new InputProperty();
            ip[i].Name = "udf:" + nvPairs[i].Name;
            ip[i].Val = nvPairs[i].Value;
        }
        update.Items = ip;
        return update;
    }
于 2012-08-23T20:39:59.227 回答
0

通常,数组需要常量来初始化它们的大小。您可以扫描一次 nvPairs 以获得长度,然后“动态地”使用这样的长度变量创建一个数组。

InputProperty[] ip = (InputProperty[])Array.CreateInstance(typeof(InputProperty), length);

不过,我不会推荐它。只要坚持

List<InputProperty> ip = ...
...
update.Items = ip.ToArray();

解决方案。它的性能并没有那么低,而且看起来更好。

于 2009-03-25T20:06:07.557 回答
0

您可以通过这种方式动态创建数组:

 static void Main()
    {
        // Create a string array 2 elements in length:
        int arrayLength = 2;
        Array dynamicArray = Array.CreateInstance(typeof(int), arrayLength);
        dynamicArray.SetValue(234, 0);                              //  → a[0] = 234;
        dynamicArray.SetValue(444, 1);                              //  → a[1] = 444;
        int number = (int)dynamicArray.GetValue(0);                      //  → number = a[0];


        int[] cSharpArray = (int[])dynamicArray;
        int s2 = cSharpArray[0];

    }
于 2012-12-20T20:25:34.220 回答