replacing an element in List<T> & downcast

B

Berryl Hesh

I have a list of base class items and I need an operation to replace an item
that matches some criteria. The problem I'm having is that the state
information I need to use FindIndex or something similar is in a derived
class. How would you go about doing that?

for the sake of discussion, here's some toy code.

class Foo
{
public int X;
public Foo(int x) { X = x; }
}
class Bar : Foo
{
int Y;
public Bar(int x, int y) : base(x) { Y = y; }
}
[Test]
public void TestCase() {
var list = new List<Foo> {new Foo(10), new Foo(8), new Bar(2, 7)};
var foundElement = list.Find(x => x.X == 10);
Assert.That(foundElement.X, Is.EqualTo(10));
// find element that is a Bar with Y = 7
}

Thanks!
 
P

Pavel Minaev

I have a list of base class items and I need an operation to replace an item
that matches some criteria. The problem I'm having is that the state
information I need to use FindIndex or something similar is in a derived
class. How would you go about doing that?

for the sake of discussion, here's some toy code.

class Foo
{
    public int X;
    public Foo(int x) { X = x; }}

class Bar : Foo
{
    int Y;
    public Bar(int x, int y) : base(x) { Y = y; }}

[Test]
public void TestCase() {
    var list = new List<Foo> {new Foo(10), new Foo(8), new Bar(2, 7)};
    var foundElement = list.Find(x => x.X == 10);
    Assert.That(foundElement.X, Is.EqualTo(10));
    // find element that is a Bar with Y = 7

}

So basically you need to find an element in a collection that 1) is a
Bar (and not all of them are), and 2) has Y=7. So:

var foundElement = (Bar)list.Find(o => o is Bar && ((Bar)o).Y == 7);

This gets a bit ugly with all the casts, and e.g. StyleCop will
complain about "is" followed by a cast, and will suggest using "as"
instead, which requires a statement lambda:

var foundElement = (Bar)list.Find(foo => { var bar = foo as Bar;
return bar != null && bar.Y == 7; });

Now, since you're using "var", you probably use .NET 3.5 as well, in
which case you might want to use Enumerable.OfType<T>(), which hides
all this uglyness:

var foundElement = list.OfType<Bar>().FirstOrDefault(o => o.Y == 7);
 
B

Berryl Hesh

How cool is that? Per-fect response, && THANK YOU

I have a list of base class items and I need an operation to replace an
item
that matches some criteria. The problem I'm having is that the state
information I need to use FindIndex or something similar is in a derived
class. How would you go about doing that?

for the sake of discussion, here's some toy code.

class Foo
{
public int X;
public Foo(int x) { X = x; }}

class Bar : Foo
{
int Y;
public Bar(int x, int y) : base(x) { Y = y; }}

[Test]
public void TestCase() {
var list = new List<Foo> {new Foo(10), new Foo(8), new Bar(2, 7)};
var foundElement = list.Find(x => x.X == 10);
Assert.That(foundElement.X, Is.EqualTo(10));
// find element that is a Bar with Y = 7

}

So basically you need to find an element in a collection that 1) is a
Bar (and not all of them are), and 2) has Y=7. So:

var foundElement = (Bar)list.Find(o => o is Bar && ((Bar)o).Y == 7);

This gets a bit ugly with all the casts, and e.g. StyleCop will
complain about "is" followed by a cast, and will suggest using "as"
instead, which requires a statement lambda:

var foundElement = (Bar)list.Find(foo => { var bar = foo as Bar;
return bar != null && bar.Y == 7; });

Now, since you're using "var", you probably use .NET 3.5 as well, in
which case you might want to use Enumerable.OfType<T>(), which hides
all this uglyness:

var foundElement = list.OfType<Bar>().FirstOrDefault(o => o.Y == 7);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top