Declaring explicit type instead of var in select statement

时光怂恿深爱的人放手 提交于 2021-02-16 14:20:34

问题


I'm doing the following request. It works as supposed to and returns data structured correctly. (It creates an element with "head" corresponding to the common field and puts the all elements of the same value in that field as a an Array in the "tail".)

var result
  = from A in As
    group A by A.F into B
    select new 
    {
      F1 = B.Key,
      F2 = from A in As
           where A.F == B.Key
           select A
    };

Now I'd like to declare it's type explicitly. I've checked in the debugger that my assumption on types is correct, however, when I try to declare that, it gives me conversion errors.

  1. Why?
  2. How can I declare the type explicitly?

I've tried different variant of declarations and as but failed.

IEnumerable<Tuple<String, IEnumerable<MyType>>> result 
  = from ...
    } as Tuple<String, MyType>;

I know it's doable but I lack the experience to get it right. I've noticed that the following works. However, I'm not sure how to take it a step further, exchanging Object for the actual variable type.

IEnumerable<Object> result 
  = from ...
    } as Object;

回答1:


Although you know that the object "insides" are the same, C# is statically typed and resolves types based on their metadata (name, namespace...), not on their members. You select an anonymous type, not a Tuple, so the type resolver cannot "agree" with it being used as a Tuple.

If you hover over the var keyword in Visual Studio, it will tell you what type is it (because it must be known during compile time, unless it's a dynamic). However due to the fact you are using anonymous type, you will not be able to write the type explicitly - it has no name in the C# source code.

What you might do is either define the type elsewhere

internal class MyObj
{
    public MyObj(string head, IEnumerable<Foo> tail)
    {
        Head = head;
        Tail = tail;
    }

    public string Head { get; set; }
    public IEnumerable<Foo> Tail { get; set; }
}

and then use it in your query:

IEnumerable<MyObj> result
  = from A in As
    group A by A.F into B
    select new MyObj(
        B.Key,
        from A in As
        where A.F == B.Key
        select A);

or use a Tuple as Jon suggested here.




回答2:


The type of the enumerable sequence produced is determined by the type of the expression after the select clause, so:

select Tuple.Create(
    B.Key,
    (from A in As where A.F == B.Key select A).ToList()
)



回答3:


Since you're creating an anonymous type with the select new {... } you have to use var. There is no way to express the type explicitly.




回答4:


You can't explicitly declare the type because by saying

select new {
   Member = Value
}

you're using an anonymous type - such types have unspeakable names and so this is one of the cases where you must use var.




回答5:


Tuple<String, IEnumerable<MyType>> <=> Tuple<String, MyType> this at first, but problem not here, you cant cast anonymous type to Tuple. You must explicitly define type then use it.

public class YourClass
{
    public string F1 {get; set;}
    public IEnumerable<MyType> F2 {get; set;}
} 

IEnumerable<YourClass> result
  = from A in As
    group A by A.F into B
    select new YourClass
    {
      F1 = B.Key,
      F2 = from A in As
           where A.F == B.Key
           select A
    };


来源:https://stackoverflow.com/questions/14359007/declaring-explicit-type-instead-of-var-in-select-statement

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!