Substituir um item de coleção usando Linq
-
09-09-2019 - |
Pergunta
Como faço para localizar e substituir uma propriedade usando Linq neste cenário específico abaixo:
public interface IPropertyBag { }
public class PropertyBag : IPropertyBag
{
public Property[] Properties { get; set; }
public Property this[string name]
{
get { return Properties.Where((e) => e.Name == name).Single(); }
//TODO: Just copying values... Find out how to find the index and replace the value
set { Properties.Where((e) => e.Name == name).Single().Value = value.Value; }
}
}
Obrigado por ajudar com antecedência.
Solução
Não use LINQ porque não vai melhorar o código porque LINQ é projetado para coleta de consulta e não para modificá-los. Eu sugiro o seguinte.
// Just realized that Array.IndexOf() is a static method unlike
// List.IndexOf() that is an instance method.
Int32 index = Array.IndexOf(this.Properties, name);
if (index != -1)
{
this.Properties[index] = value;
}
else
{
throw new ArgumentOutOfRangeException();
}
Por que Array.Sort () e Array.indexOf () métodos estáticos?
Além disso, sugiro não usar uma matriz. Considere o uso de IDictionary<String, Property>
. Isto simplifica o código para o seguinte.
this.Properties[name] = value;
Note que nem solução é thread-safe.
Um ad hoc LINQ solução -. Você vê, você não deve usá-lo, porque todo o conjunto será substituído por um novo
this.Properties = Enumerable.Union(
this.Properties.Where(p => p.Name != name),
Enumerable.Repeat(value, 1)).
ToArray();
Outras dicas
[Nota: esta resposta foi devido a um mal-entendido sobre a questão - ver os comentários sobre esta resposta. Aparentemente, eu sou um pouco densa :(] É a sua 'propriedade' de uma classe ou um struct?
Este teste passa para mim:
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
public interface IPropertyBag { }
public class PropertyBag : IPropertyBag
{
public Property[] Properties { get; set; }
public Property this[string name]
{
get { return Properties.Where((e) => e.Name == name).Single(); }
set { Properties.Where((e) => e.Name == name).Single().Value = value.Value; }
}
}
[TestMethod]
public void TestMethod1()
{
var pb = new PropertyBag() { Properties = new Property[] { new Property { Name = "X", Value = "Y" } } };
Assert.AreEqual("Y", pb["X"].Value);
pb["X"] = new Property { Name = "X", Value = "Z" };
Assert.AreEqual("Z", pb["X"].Value);
}
Eu tenho que saber por que o getter retorna um 'propriedade' em vez de qualquer tipo de dados .Value, mas ainda estou curioso porque você está vendo um resultado diferente do que o que eu sou.