+2  A: 

Do not use LINQ because it will not improve the code because LINQ is designed to query collection and not to modify them. I suggest the following.

// 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();
}

Why are Array.Sort() and Array.IndexOf() methods static?

Further I suggest not to use an array. Consider using IDictionary<String, Property>. This simplifies the code to the following.

this.Properties[name] = value;

Note that neither solution is thread safe.


An ad hoc LINQ solution - you see, you should not use it because the whole array will be replaced with a new one.

this.Properties = Enumerable.Union(
   this.Properties.Where(p => p.Name != name),
   Enumerable.Repeat(value, 1)).
   ToArray();
Daniel Brückner
"Do not use LINQ because it will not improve the code" without justification, this statement is useless
spender
Clearified the point.
Daniel Brückner
@danbruc: Unfortunately, using [I]Dicitonary is not option as it's not serializable... Have to leave it an array... yeah... IndexOf() seems a reasonable solution... but I was just hoping may be I was doing something wrong and there's indeed a way in Linq to do this...
Vyas Bharghava
Dictionary<K,V> is Serializable....
Jonathan
XML Serializable?
Vyas Bharghava
A: 

[note: this answer was due to a misunderstanding of the question - see the comments on this answer. Apparently, I'm a little dense :(] Is your 'Property' a class or a struct?

This test passes for me:

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);
}

I have to wonder why the getter returns a 'Property' instead of whatever datatype .Value, but I'm still curious why you're seeing a different result than what I am.

Jonathan
It's a class... Comment re-pasted from above: The code above works because I'm not replacing the entire item in the Property[] array. The comment in the code illustrates that: //TODO: Just copying values... Find out how to find the index and replace the value
Vyas Bharghava
And hey Jonathan, I do appreciate you taking time out to help. Not an ungrateful moron, you see... :)
Vyas Bharghava
Could you paste in more of your code then? The code I posted worked for me, and that's the only thing I can think of that would make it work like you describe.
Jonathan
The point is the following: "[...]Single().Value = value.Value;" just updates the value of the property but does not replace the property object in the array with the supplied one. This would require something like "[...]Single() = value;". Obvisiously this does not work - LINQ does not support
Daniel Brückner
modifying collection. You have to build a new one and replace the old one with that - see the example in my answer - but this is not a smart solution.
Daniel Brückner
Ah, I see what the real question is. Yes, you cannot modify the collection with LINQ. Language integrated **query**, not update.
Jonathan
Vyas Bharghava
Well, there's List<T>.FindIndex, but that's not available on Array (and I'm guessing the .ToList() would kind of defeat the purpose). That said, you should be able to write a custom extension method to implement FindIndex on a array if you really want to.
Jonathan