1

假设我有一个从Animal和派生的异构类型序列Food

这应该在派生类型的实例中进行转换FedNotFedBadFed.

var seq1 = new[] { new Fish(), new FishFood(), new Horse(), new DogFood(), new Dog() };

应该变成

var seq2 = new [] {  new FishFed(), new HorseBadFed(), new DogNotFed() };

逻辑是:

  • 如果 anAnimal在下一个元素中有适当的食物,XXXFed则创建一个实例;

  • 如果下一个元素有食物。但对此不好Animal-> XXXBadFed;

  • 否则,如果不是下一个元素中的食物 -> XXXNotFed

在下一项上使用条件处理一个序列,这对于迭代来说并不简单。

如何使用 Linq 或IEnumerable<T>扩展方法来抽象涉及状态的序列处理?

我知道Aggregate使用累加器功能来做类似的事情;这是我的情况吗?或者更好的可以用它来创建一个新的序列?

在没有命令式代码的情况下使用memoization函数解决此类问题是否正确?

4

2 回答 2

3

我将首先使用 Zip 函数创建对,然后改为处理对的集合。

        var seq1 = new object[] { new Fish(), new FishFood(), new Horse(), new DogFood(), new Dog() };
        var count = seq1.Length;
        var foodSeq = seq1.Skip(1).Concat(new object[]{null});
        var dinnerPairs = seq1.Zip(foodSeq, (eater, food) => Tuple.Create(eater as Animal, food as Food)).Where(t => t.Item1 != null);
        var result = dinnerPairs.Select(t => t.Item1.Feed(t.Item2));

Animal 类的 Feed 方法将被每个动物覆盖。例如对于狗,它会在 null 的情况下返回 DogNotFed,在 DogFood 的情况下返回 DogFad,否则返回 DogBadFed。如果您有严格的命名约定,则可以使用反射动态创建这些类型。

public abstract class Animal
{
    public abstract Animal Feed(Food food);
}

编辑:我如何想象 Feed 方法可以使用反射解决您的逻辑,但未经测试。

public Animal Feed(Food food)
    {
        var myType = this.GetType().FullName;
        if (food == null) return GetNewObject(myType + "NotFed") as Animal;
        if( food.GetType().FullName == myType+"Food") return GetNewObject(myType+"Fed") as Animal;
        return GetNewObject(myType+"BadFed") as Animal;
    }

    public static object GetNewObject(string typeName)
    {
        try
        {
            var t = Type.GetType(typeName);
            return t.GetConstructor(new Type[] { }).Invoke(new object[] { });
        }
        catch
        {
            return null;
        }
    }
于 2013-03-10T10:27:38.500 回答
-1

在现实生活中,谁负责吃东西、生病、饱或仍然饿着肚子?这将是动物本身。

那么为什么不让一个类型IConsumeFood实现一个接口呢?Animal它的方法Consume会得到一些food并返回食物消耗的结果。

然后你就可以对每只动物调用这个方法,把你所有的食物(整个数组)放在那里,让动物决定吃什么,不吃什么,然后返回适当的结果,例如 XXXFed、XXXNotFed , ETC。

我希望你在这里避免的是使用类型名称或周围有大量“ifs”的操作。即使是原型设计也太脏了。想想责任和顾虑,这就是为什么我们首先要有 OOP :)

于 2013-03-10T10:18:50.087 回答