首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >混凝土浇筑IEnumerable界面

混凝土浇筑IEnumerable界面
EN

Stack Overflow用户
提问于 2017-03-20 14:28:14
回答 5查看 2K关注 0票数 1

我有这样的东西:

代码语言:javascript
复制
    public interface IThing
    {
        string Id { get; }
    }
    public class Ball : IThing
    {
        public string Id { get; }
    }

    public class Car : IThing
    {
        public string Id { get; }
    }

对于我的3-4函数,我想对BallCar进行同样的处理。我使用这个界面,所以我不需要做过载的方法(一种用于汽车,一种用于球)。

最后,在函数中,如果是BallCar,则有不同的逻辑。我得到一个IEnumerable<IThings>,我想将它转换为IEnumerable<Car>IEnumerable<Ball>,这取决于它由什么组成。如果它是混合的,我希望它失败。必须是所有的汽车或所有的球。

我试过这样的方法:

代码语言:javascript
复制
        var things = (inputs is IEnumerable<Ball>) ? input.Locations.Cast<Ball>() : input.Locations.Cast<Car>()

但它不喜欢那样。什么是推荐的方法,我可以有一个变量?

编辑:

我之所以想把它放到一个变量中,是因为我将它发送到重载的方法中。所以我想这么做:

代码语言:javascript
复制
        var things = (inputs is IEnumerable<Ball>) ? input.Locations.Cast<Ball>() : input.Locations.Cast<Car>()

        for (var i = 0; i < numRequests; i++)
        {
            var thingsSet = things.Skip(i * 1000).Take(1000);
            var results = callOverLoadedFunction(thingsSet);
        }

而不是这样:

代码语言:javascript
复制
        if (inputs is IEnumerable<Ball>)
        {
            var things = input.Locations.Cast<Ball>();
            for (var i = 0; i < numRequests; i++)
            {
                var thingsSet = things.Skip(i * 1000).Take(1000);
                var results = callOverLoadedFunction(thingsSet);
            }
        }
        else
        {
            var things = input.Locations.Cast<Car>();
            for (var i = 0; i < numRequests; i++)
            {
                var thingsSet = things.Skip(i * 1000).Take(1000);
                var results = callOverLoadedFunction(thingsSet);
            }
        }
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2017-03-20 14:47:30

您的尝试中的问题是:

代码语言:javascript
复制
inputs is IEnumerable<Ball>

因为只包含Ball类型元素的BallIEnumerable<Ball>的类型不同。您真的别无选择,只能在集合中进行枚举,以确定每个项是否符合您所需的类型。您可以使用.Cast<...>()并处理InvalidCastException,但这有点麻烦。另一种方法是使用OfType<...>

代码语言:javascript
复制
var cars = inputs.OfType<Car>();
var balls = inputs.OfType<Ball>();

现在,您可以根据自己的意愿处理这些问题,例如:

代码语言:javascript
复制
if(balls.Any() && cars.Any())
{
    //You're not allowed to have balls and cars together
    throw new Exception(...);
}

然而,你真的打破了固体的开放/封闭原则在这里,它似乎你应该考虑在一个更高的层次,你正在努力实现什么。

票数 2
EN

Stack Overflow用户

发布于 2017-03-20 14:44:28

您可以执行一个转换方法,但这仍然会破坏一些原则,因为您仍然需要放置一个if语句。我不确定,您正在使用的接口与您想要实现的正确的方式。

如果您希望car在特定情况下的行为与ball不同,那么car中的实现将执行而不是球中的实现。

不要试图从外部调整接口。实现必须这样做。

为什么不用DoMySpecialStuffIThing中创建一个方法,然后在这个特殊的方法中迭代您的可枚举方法,该方法只对所有元素调用DoMySpecialStuff?这样你才能避免你的if-语句。

我刚看到你用overloadedMethod编辑

所以它可以这样工作:

代码语言:javascript
复制
for (var i = 0; i < numRequests; i++)
    {
        var thingsSet = things.Skip(i * 1000).Take(1000);
        var results = callOverLoadedFunction(thingsSet);
    }

void OverLoadedFunction(IThing thing)
{
    thing.DoSpecialStuff(); // This does different things in car/ball
}
票数 1
EN

Stack Overflow用户

发布于 2017-03-20 14:47:55

您可以使用LINQ将球和汽车分开。

代码语言:javascript
复制
IEnumerable<Ball> balls = things.OfType<Ball>();
IEnumerable<Car> cars = things.OfType<Car>();

如果您希望它失败,并像一行解决方案一样,尝试这样的方法

代码语言:javascript
复制
IEnumerable<Ball> balls = things.OfType<Ball>().Count() == things.Count() ? things.OfType<Ball>() : null; //or whatever you want
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42906207

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档