How can i define and explicit tell to compiler that i want a listof a AnonymousType, from a query?
I dont want to use the "var" keyword
Follows the example:
List<string> query = // Explicit getting a List<string>
(from l in listTest
select l).ToList();
Thats what i am trying to do:
var query2 = // I would like to use List<´a> instead of var
(from l in listTest
select new
{
_string = l,
Lenght = l.Length
}).ToList();
The only possible way to define the type of that local variable as the actual type of such a list is to use var. You could type the variable as a less-derived type, for example using IList (the non-generic version) or object or dynamic, but given that the anonymous type does not have a name, there is no way to explicitly name that type. If you have a need to do so you would need to use a named type instead of an unnamed type.
Of course, if you don't technically want to use a local variable you can use an generic method that takes an action to allow you to use generic method inference rather than local variable type inference to type your identifier. Using a Use method:
public static void Use<T>(T item, Action<T> action)
{
action(item);
}
Use(from l in listTest
select new
{
_string = l,
Lenght = l.Length
},
query => Console.WriteLine(string.Join("\n", query)));
You now have an identifier (technically it's a parameter to a method, not a local) typed as the exact type of that list, without using var.
Related
I'm wondering how does this code work:
dynamic dynaString = 2;
string b = dynaString.ToString();
When this one is not working:
var list = new List<dynamic>();
var liststring = new List<string>();
liststring = list.Select(x => x.ToString()).ToList();
I know I can add Cast<string> after Select statement but that does not explain that behaviour. Why does ToString() on dynamic element work different when called on dynamic variable declared in code than on dynamic variable taken from list in LINQ.
I've looked into method signature of Select and it's:
My guess is that x here is a dynamic variable, so it should behave just like dynaString, but it's not. Intellisense is suggesting me that this x.ToString() returns string:
Anyone got experience with dynamics in C# and can explain me that?
I've also tried this code:
var list = new List<dynamic>();
var liststring = new List<string>();
foreach (dynamic a in list)
{
liststring.Add(a.ToString());
}
It compiles as expected, because again the a is declared as dynamic in foreach statement.
According to dynamic type docs:
The dynamic type indicates that use of the variable and references to its members bypass compile-time type checking. Instead, these operations are resolved at run time.
Type dynamic behaves like type object in most circumstances. In particular, any non-null expression can be converted to the dynamic type. The dynamic type differs from object in that operations that contain expressions of type dynamic are not resolved or type checked by the compiler.
There is no way to infer type from usage in case type checking and/or resolution is bypassed at compile-time.
If you omit generic type parameter it will by default return dynamic type even you call ToString() method. The reason is that any non-null expression can be assigned to dynamic. As dynamic is source, it will be also the result of Select(x => x.ToString()) method call.
On the other hand you can assign dynamic object to string variable as you are calling ToString() which returns string instance.
I have a method call like this:
public bool IsAlright(...)
{
var myColumns = // some linq query.ToArray();
var theirColumns = (from row in System.IO.File.ReadAllLines(#"ConfigColumns.txt")
where !string.IsNullOrWhiteSpace(row)
select new { TheColumn = row.ToUpper() }).ToArray();
bool isAlright = // join those two above and see if they have anything in commmon.FirstOrDefault
return isAlright;
}
But I think reading the text file every time is a performance hit and I can do it just once.
So I am thinking of pulling it out but how? it is a "var" and I don't know how to pull out a "var" and define it out of the method scope like a cached object or something?
The var keyword is not a type, it just means the compiler will infer the type based on the type of the right-hand side expression.
The type of your var is an array of an anonymous type. You can't declare a field or method of an anonymous type (unless you use object or dynamic), so you need to declare a type that matches the interface of your anonymous object.
In your case, since you're only storing a string, I would recommend, just returning an array of string instead of using an object:
string[] theirColumns = (from row in System.IO.File.ReadAllLines(#"ConfigColumns.txt")
where !string.IsNullOrWhiteSpace(row)
select row.ToUpper()).ToArray();
You can now pull theirColumns out to a field in your class.
You cannot use var outside of method scope. In your case you can either use string[] instead of custom anonymous object, or create a custom class. Then promote the variable to class field and use it in any other method that you need.
First, Declare a class outside the method.
public class YourClassName
{
public string TheColumn {set;get;}
}
I assume each row is just a string, change the type if it's not
change your theirColumns to
YourClassName[] theirColumns = (from row in System.IO.File.ReadAllLines(#"ConfigColumns.txt")
where !string.IsNullOrWhiteSpace(row)
select new YourClassName { TheColumn = row.ToUpper() }).ToArray();
extract it outside the method.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I pass an anonymous type to a method?
I have the following LINQ Statement, whose output has to be processed in another method:
var data = from lines in File.ReadAllLines(TrainingDataFile)
.Skip(ContainsHeader ? 1 : 0)
let f = lines.Split(new[] { FieldSeparator }).ToList<String>()
let target = f[TargetVariablePositionZeroBased]
select new { F=f, T=target };
What should be the datatype of the parameter in the method that will take this data?
You can not return the anonymous data types from a method. You can define a class and return object of that class from query and pass it to target method.
public class SomeClass
{
public string F {get; set;}
public string T {get; set;}
}
var data = from lines in File.ReadAllLines(TrainingDataFile)
.Skip(ContainsHeader ? 1 : 0)
let f = lines.Split(new[] { FieldSeparator }).ToList<String>()
let target = f[TargetVariablePositionZeroBased]
select new SomeClass { F=f, T=target };
You can pass the query result IEnumerable<SomeClass> to method as parameter.
public void MethodToCall(IEnumerable<SomeClass> someClass)
{
}
To call the method by passing the query result (IEnumerable<SomeClass>) that is stored in data in this sample code
MethodToCall(data);
You can't very easily pass anonymous types around. You can either create a class, or since your data has only two properties, use a Tuple:
select new Tuple<List<string>, string> (f, target);
If I have the data types correct, then the data type of the parameter would be:
IEnumerable<Tuple<List<string>, string>>
and you would reference F and T using the Tuple properties Item1 and Item2.
1) Just to pass the result of the query, make your function generic, that will do:
var data = from lines in File.ReadAllLines(TrainingDataFile)
.Skip(ContainsHeader ? 1 : 0)
let f = lines.Split(new[] { FieldSeparator }).ToList<String>()
let target = f[TargetVariablePositionZeroBased]
select new { F=f, T=target };
SomeMethod(data);
public void SomeMethod<T>(IEnumerable<T> enumerable)
{
// ^^choose the return type..
}
Simple. If the processing inside the method is something so simple this will do. But you won't be able to access properties F and T inside the method.
To do so:
2) You can use the "cast by example" trick shown here by Eric. To quote him:
We use method type inference and local variable type inference to tell
the compiler "these two things are the same type". This lets you
export an anonymous type as object and cast it back to anonymous type.
...the trick only works if the example and the source objects were
created in code in the same assembly; two "identical" anonymous types
in two different assemblies do not unify to be the same type.
SomeMethod(data);
public void SomeMethod(IEnumerable<object> enumerable)
{
var template = new { F = new List<string>(), T = string.Empty };
foreach (var item in enumerable)
{
var anonymousType = item.CastToTypeOf(template);
//print string.Join(", ", anonymousType.F) + " - " + anonymousType.T //compiles
//or whatever
}
}
//a more generic name perhaps is 'CastToTypeOf' as an extension method
public static T CastToTypeOf<T>(this object source, T example) where T : class
{
return (T)source;
}
The catch here is that SomeMethod now is tailor made for your anonymous type, since you're specifying a specific type inside the method, so its better to not make the function generic (though you can do) and to give a suitable name for the function.
3) If function is just for your unique type now, I would better have them all wrapped in a single method and not pass at all - no hassle! :)
4) Or you can delegate the action to be done on your anonymous type. So method signature would be like:
SomeMethod(data, d => print string.Join(", ", d.F) + " - " + d.T);
public void SomeMethod<T>(IEnumerable<T> enumerable, Action<T> actor)
{
foreach (var item in enumerable)
actor(item);
}
If it matters you can have Func delegate as well by having one more type argument.
5) Rely on fiddly reflection to get the properties from your anonymous type otherwise.
6) Use dynamic keyword on method argument and now you have dynamic typing. Both the above doesnt give you benefits of static typing.
7) You will be better off having a separate class that holds F and T. And that the best of all. But ask yourself do they together represent something as an entity?
8) If not, just pass an IEnumerable<Tuple> or IDictionary depending on what matters.
It all depends on what/how you want to achieve with the method. Personally, I would go for the approach 2 in a hobby project (for the fun involved), but in production code 3, 4, 7, 8 depending on the context.
I've have the following code example from Microsoft (http://msdn.microsoft.com/en-us/library/bb534869.aspx):
String[] fruits = {"apple", "banana", "mango", "orange", "passionfruit", "grape" };
var query = fruits.Select((fruit, index)
=> new {Substring = fruit.Substring(0, index)});
foreach (var obj in query)
Console.WriteLine("{0}", obj);
This works quite well, but what I m not understand is what type of query is?
I ve tried to get out the info from the debugger but i was not able to declare it and write it down explicitly. I ve tried several variants e.g.
IEnumerable<int,string> query = fruits.Select((fruit, index)
=> new {Substring = fruit.Substring(0, index)});
but this does build at all. How can I define the query type explicit without using var?
You cannot specify type because it is anonymous. Read more here:
http://msdn.microsoft.com/en-us/library/bb397696.aspx
When you use the new operator without a specific type, then the compiler creates an anonymous type that you can't refer to explicitly. If you want to be able to refer to it, then you should either create your own class to return explicitly, or return a pre-existing class. Try:
IEnumerable<string> query = fruits.Select((fruit, index) => fruit.Substring(0, index));
Just for completeness, if you really must specify the type (and there really is no need to - an anonymous type is just as type-safe) then you must first declare a class/struct
public class FruitySubstringyThingy
{
public string Substring{get;set;}
}
and use that in the projection
IEnumerable<FruitySubstringyThingy> items
= fruits.Select((fruit,index) => new FruitySubstringyThingy{Substring = fruit.Substring(0, index)});
I have the following dictionary in a method:
var nmDict = xelem.Descendants(plantNS + "Month").ToDictionary(
k => new Tuple<int, int, string>(int.Parse(k.Ancestors(plantNS + "Year").First().Attribute("Year").Value), Int32.Parse(k.Attribute("Month1").Value), k.Ancestors(plantNS + "Report").First().Attribute("Location").Value.ToString()),
v => {
var detail = v.Descendants(plantNS + "Details").First();
return
new
{
BaseHours = detail.Attribute("BaseHours").Value,
OvertimeHours = detail.Attribute("OvertimeHours").Value
};
});
I need to return nmDict. The problem is that I cannot figure out how to label my method signature. I have tried the following:
protected IDictionary<XElement, XElement> OvertimereportData(HarvestTargetTimeRangeUTC ranges)
The above gives me this error:
Cannot implicitly convert type System.Collections.Generic.Dictionary<System.Tuple<int,int,string>,AnonymousType#1>' to 'System.Collections.Generic.IDictionary<System.Xml.Linq.XElement,System.Xml.Linq.XElement>'. An explicit conversion exists (are you missing a cast?)
protected IDictionary<Tuple, XElement> OvertimereportData(HarvestTargetTimeRangeUTC ranges)
gives me this error:
'System.Tuple': static types cannot be used as type arguments
I do not know what to do.
The short answer: You can't return anonymous types from a function.
The long answer: Your dictionary's value type is anonymous {BaseHours, OvertimeHours} which cannot be returned from a function or passed as an argument (except as an object, but that does nobody any good unless you go through the hassle of reflecting into it). Either define a class/struct with BaseHours and OvertimeHours in it, or use a tuple. The former is probably slightly better because you can keep the names BaseHours and OvertimeHours; with a tuple you just get Value1 and Value2.
If you are using C# 4.0 than you can return the anonymous via dynamic type. So your method signature would look like this
protected IDictionary<Tuple<int,int,string>, dynamic> OvertimereportData(HarvestTargetTimeRangeUTC ranges)
And through the dynamic object you can find the properties at run time.
Hope this will help you.
When you call the ToDictionary method, the resulting dictionary's type has little to do with the type of elements in your source sequence. It's defined entirely by the data types returned by the key and value expressions you supply to the call. For example, if you were to call:
xelem.Descendants(plantNS + "Month").ToDictionary(
k => int.Parse(k.Attribute("Year").Value),
v => k.Attribute("Year).Value
);
You would get an IDictionary<int, string> because that's what your two expressions returned. To return that from a method, you just need to construct the correct type, based on your expressions.
Your first one is easy:
k => new Tuple<int, int, string>(...)
The second one, though, is going to be a problem. The values in your dictionary are of an anonymous type: you return a new { } without specifying a concrete type name for that value. In general, that is going to make it impossible for you to use that dictionary as a return value or parameter. (It can be done, using some very strange-looking generic techniques, but I wouldn't recommend it.)
The first thing you'll need to do, then, is make a concrete type to hold your values, e.g.
public class HoursContainer
{
public string BaseHours { get; set; }
public string OvertimeHouse { get; set; }
}
and change your Linq query appropriately:
var detail = v.Descendants(plantNS + "Details").First();
return new HoursContainer
{
BaseHours = detail.Attribute("BaseHours").Value,
OvertimeHours = detail.Attribute("OvertimeHours").Value
};
Once you've done this, your dictionary will have a concrete type based on the types of things you specified when you created it:
IDictionary<Tuple<int, int, string>, HoursContainer>
(Note: You could also just use another Tuple<int, int> or whatever here, if you wanted, but the resulting generic type would get unwieldy very fast.)