Como definir comprimento de matriz em c # dinamicamente
-
22-08-2019 - |
Pergunta
Eu ainda sou novo para C # e eu estive lutando com várias questões sobre matrizes. Eu tenho uma matriz de objetos de metadados (pares de valores de nome) e eu gostaria de saber como criar apenas o número de "InputProperty" objetos que eu realmente precisa. Neste circuito eu definir arbitrariamente o número de elementos a 20 e eu tento salvar quando a entrada torna-se nulo, mas o serviço web no fim de recepção de isto não faz como quaisquer elementos nulos passados ??para ele:
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;
}
Em resumo, dizem que eu só tenho 3 pares NameValue na matriz de entrada acima? Em vez de alocar 20 elementos para a matriz chamada ip, como pode codificar isso para ip é somente tão grande quanto ele precisa ser. O objecto de actualização é passado através de um outro modo de serviço Web serialização é importante (isto é, que não podem usar NameValueCollection, etc).
P.S. É a única maneira de followup em uma pergunta postada através do "adicionar comentários" facilidade?
Solução
Se você não quiser usar um List
, ArrayList
, ou outra coleção dinamicamente de tamanho e, em seguida, converter para uma matriz (que é o método eu recomendo, por sinal), então você vai ter que alocar o matriz para seu tamanho máximo possível, manter o controle de quantos itens você colocar nele, e, em seguida, criar uma nova matriz com apenas esses itens nele:
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;
}
Um método alternativo seria para sempre update.Items = ip;
atribuir e, em seguida, redimensionar, se necessário:
update.Items = ip;
if (i < nvPairs.Length)
{
Array.Resize(update.Items, i);
}
É menos código, mas provavelmente vai acabar fazendo a mesma quantidade de trabalho (ou seja, a criação de uma nova matriz e copiar os itens antigos).
Outras dicas
InputProperty[] ip = new InputProperty[nvPairs.Length];
Ou, você pode usar uma lista como assim:
List<InputProperty> list = new List<InputProperty>();
InputProperty ip = new (..);
list.Add(ip);
update.items = list.ToArray();
Outra coisa que eu gostaria de salientar, em C # você pode delcare seu uso variável int em um para a direita loop dentro do loop:
for(int i = 0; i<nvPairs.Length;i++
{
.
.
}
E só porque eu estou no clima, aqui está uma maneira mais limpa de fazer esse método 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;
}
Será que é preciso para ser um array? Se você usar um ArrayList ou um dos outros objetos disponíveis em C #, você não tem esta limitação para o conteúdo com. Hashtable, IDictionnary, IList, etc .. todos permitem um número dinâmico de elementos.
Use esta:
Array.Resize(ref myArr, myArr.Length + 5);
Você pode usar Lista de dentro do método e transformá-lo em uma matriz no final. Mas eu acho que, se falamos de um valor máximo de 20, seu código é mais rápido.
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;
}
Ou em C # 3.0 usando System.Linq
você pode ignorar a lista intermediário:
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;
}
Use Array.CreateInstance
para criar uma matriz dinâmica.
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;
}
Normalmente, as matrizes exigem constantes para inicializar o seu tamanho. Você poderia varrer nvPairs uma vez para obter o comprimento, em seguida, "dinamicamente" criar uma matriz usando uma variável para o comprimento como esta.
InputProperty[] ip = (InputProperty[])Array.CreateInstance(typeof(InputProperty), length);
Eu não recomendaria isso, porém. Basta ficar com o
List<InputProperty> ip = ...
...
update.Items = ip.ToArray();
solução. Não é que muito menos eficaz, e muito melhor olhando.
Você pode criar uma matriz dinâmica desta forma:
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];
}