不能缩短界面

时间:2010-10-04 21:43:26

标签: c# .net linq

我有这个属性,工作正常:

public IEnumerable<IGrouping<MessageType, Message>> MessageGroups
{
    get
    {
        return
            (from msg in _messages
                orderby msg.Type descending
                group msg by msg.Type);
    }
}

然而,这导致我不得不在我的代码中的几个地方重复看起来很丑陋的IEnumerable<IGrouping<MessageType, Message>>。我试图通过定义这样一个简单的包装器界面来使这更容易:

public interface IMessageGroups :
    IEnumerable<IGrouping<MessageType, Message>> { }

并将上面的属性更改为:

public IMessageGroups MessageGroups
{
    get
    {
        return
            (IMessageGroups)
            (from msg in _messages
                orderby msg.Type descending
                group msg by msg.Type);
    }
}

这构建很好,但在运行时我得到:

  

无法投射类型的对象   'System.Linq.GroupedEnumerable`3 [消息,消息类型,消息]'   输入'IMessageGroups'。

(从错误消息中删除了特定于项目的命名空间)

我该怎么做才能解决这个问题?

4 个答案:

答案 0 :(得分:3)

您可以尝试使用type alias

using Foo = IEnumerable<IGrouping<MessageType, Message>>;

然后:

public Foo MessageGroups
{
    get
    {
        return
            (from msg in _messages
             orderby msg.Type descending
             group msg by msg.Type);
    }
}

另一种可能性是进一步扩展您的LINQ查询并选择您在分组后创建的某些自定义类型:

public IEnumerable<Foo> MessageGroups
{
    get
    {
        return
            (from msg in _messages
             orderby msg.Type descending
             group msg by msg.Type
             select new Foo { Messages = g, MessageType = g.Key }      
            );
    }
}

和Foo:

public class Foo
{
    public MessageType MessageType { get; set; }
    public IEnumerable<Message> Messages { get; set; }
}

如果您不关心延迟评估,可以在LINQ查询的末尾添加.ToArray(),返回类型只是Foo[]

答案 1 :(得分:2)

它构建正常,因为编译器永远无法确定返回的类型实际上是否实际上是实现接口的子类。 (与此类型的对比相反,您会得到编译器错误,因为 是静态已知的。)

但事实仍然是你试图将LINQ表达式的结果转换为它未实现的接口(“包装器”接口)。这根本不起作用。除了声明一个自己实现它的类,并且实际上在实现中进行“包装”(将现有的LINQ表达式传递给构造函数)之外,没有什么可以真正解决它。

答案 2 :(得分:1)

转换为IMessageGroups失败,因为查询的结果是IEnumerable<IGrouping<MessageType, Message>>的实例,而不是IMessageGroups的实例。但您可以编写一个MessageGroups类并使用它来包装查询结果:

public class MessageGroups : IMessageGroups
{
    private readonly IEnumerable<IGrouping<MessageType, Message>> _groups;

    public MessageGroups(IEnumerable<IGrouping<MessageType, Message>> groups)
    {
        _groups = groups;
    }

    public IEnumerable<IGrouping<MessageType, Message>> GetEnumerator()
    {
        return _groups.GetEnumerator();
    }

    public static MessageGroups Create(IEnumerable<IGrouping<MessageType, Message>> groups)
    {
        return new MessageGroups(groups);
    }
}

并使用它:

public IMessageGroups MessageGroups
{
    get
    {
        return
            MessageGroups.Create(
                from msg in _messages
                orderby msg.Type descending
                group msg by msg.Type);
    }
}

答案 3 :(得分:0)

在cs文件的顶部:

 using ASimpleName = Dictionary<string, Dictionary<string, List<string>>>;

Source

或在你的情况下:

using ShortName = IEnumerable<IGrouping<MessageType, Message>>;