SelectMany cannot be inferred from the usage [duplicate] - c#

This question already has an answer here:
SelectMany() Cannot Infer Type Argument -- Why Not?
(1 answer)
Closed 7 years ago.
I get the following error when I try to compile my code:
The type arguments for method
'System.Linq.Enumerable.SelectMany(System.Collections.Generic.IEnumerable,
System.Func>)'
cannot be inferred from the usage. Try specifying the type arguments
explicitly.
List<RowEntry> entries = ...
List<RowArgument> arguments = ...
var argumentsVal = entries.SelectMany((RowEntry entry) =>
(IEnumerable<RowArgumentVal>)arguments.SelectMany((RowArgument arg) =>
new RowArgumentVal()
{
Action = "X"
, EntryID = entry.ID
, ArgID = arg.ID
, Val_BIT = true
, Val_DATE = new DateTime(2014, 01, 04)
, Val_DATETIME = new DateTime(2014, 01, 04)
, Val_DECIMAL = 4.6M
, Val_INT = 88
, Val_TIME = new TimeSpan(6, 0, 0)
}
).Cast<RowArgumentVal>()).Cast<RowArgumentVal>().ToList();
I don't get how I can "type" this even further...

The problem is that the inner SelectMany isn't applicable there, and you probably meant Select.
var argumentsVal = entries.SelectMany(entry =>
arguments.Select(arg => new RowArgumentVal())).ToList();
Each entry will be mapped into an IEnumerable<RowArgumentVal> according to the arguments.
Imagine the outer SelectMany was a simple Select, and it would generate List<IEnumerable<RowArgumentVal>>. But because it is SelectMany, it will "flatten" the result into a simple List<RowArgumentVal>.
The SelectMany method expects a mapping to IEnumerable<T> - not T. Your original code would be valid if RowArgumentVal just happened to implement the IEnumerable<T> interface, which I suppose isn't the case.

That seems to be a cartesian product from both lists since there is no relation between them. You may want to join them but it's not exactly clear how.
Here is a more readable and compiling way to produce a cartesian product:
var query = from entry in entries
from argument in arguments
select new RowArgumentVal
{
Action = "X", EntryID = entry.ID, ArgID = argument.ID, // ...
};
List<RowArgumentVal> argumentsVal = query.ToList();

If you want a cartesian product try doing the following
var argumentsVal = from e in entries
from a in arguments
select new RowArgumentVal(...)

As an aside, the "further typing" you could have done would be to give the type arguments to the generic method calls. In particular, if you had changed the second SelectMany to SelectMany<RowArgument, RowArgumentVal> you would have got the errors
Cannot implicitly convert type RowArgumentVal to System.Collections.Generic.IEnumerable<RowArgumentVal>. An explicit conversion exists (are you missing a cast?)
Cannot convert lambda expression to delegate type System.Func<RowArgument,int,System.Collections.Generic.IEnumerable<RowArgumentVal>> because some of the return types in the block are not implicitly convertible to the delegate return type
which would maybe have led you to the other answers here - that you were trying to call a method that expected a sequence, but you were giving it a single object.
(Or in trying to decide which type arguments to add, you would have realised what was wrong sooner.)

Related

Error implicitly converting List<T> to CustomList<T> using LINQ?

How to convert List to List<T>?
var memberCommunicationPreferenceses = new PersonifyCollection<MemberCommunicationPreferences>();
memberCommunicationPreferenceses = (from ICustomerOptIn customerOptIn in customerData.CustomerOptIns
select new Models.MemberCommunicationPreferences()
{
MemberCommunicationsPrefernceId = customerOptIn.CustomerOptInId.ToString(CultureInfo.InvariantCulture),
ShortName = customerOptIn.OptionShortNameString,
ShortNameDescription = customerOptIn.OptionShortName.Description
.....
}).Where(x=>x.OptedInFlag).ToList();
error
Error 23 Cannot implicitly convert type 'System.Collections.Generic.List<EBusiness.Model.Models.MemberCommunicationPreferences>'
to 'EBusiness.Model.Models.Collections.PersonifyCollection<.EBusiness.Model.
Models.MemberCommunicationPreferences>' C:\\Trunk\Source\EBusiness\EBusiness.Model\Concrete\Personify\
PersonifyMemberCommunicationPreferences.cs 94 31 EBusiness.Model
update:
--
PersonifyCollection of code based on the 2nd answer in this post enter link description here
We don't know what methods your PersonifyCollection class has, so we can't tell you how to convert to it, or if it has any methods to do so. You could try:
var something=new PersonifyCollection<MemberCommunicationPreferences>(memberCommunicationPreferences);
If your custom collection implements the standard constructor that takes an IEnumerable, that should work.

using {...} with new to instantiate anonymous type in C#

I recently was trying my skill tests for C# at Smarterer.
I came across a question which says which of the following can be used to create a anonymous type in C# (something similar).
I selected "None of these" (i do not remember other options as it was time based test only had 10 sec).
Once I gave the answer it said that {...} is the right answer.
So i guess something like this:
var someVariableName = new {...}; to create a anonymous type.
I am surprise to see this and binged a bit but was not able to find anything similar to this.
Question: Is there any ways I can create a anonymous type without declaring its type while instantiating using {...} keyword or operator? or the question's correct answer was not "correct"?
This can be done using dynamic keyword if I am not wrong.
http://msdn.microsoft.com/en-GB/library/bb397696.aspx is the MS documenation, to quote:
You create anonymous types by using the new operator together with an
object initializer. For more information about object initializers,
see Object and Collection Initializers (C# Programming Guide). The
following example shows an anonymous type that is initialized with two
properties named Amount and Message.
C#
var v = new { Amount = 108, Message = "Hello" };
This is NOT a dynamic type, this a specific static type that is 'anonymous', ie you have not given it a name. However the compiler has/will and so v is still strongly typed, you get intellisense and v.FieldIDontHave will give a compiler error.
Use the keyword var
var x = new {value = 3, name = "lol"};
Console.WriteLine(x.value); //prints 3
Console.WriteLine(x.name); //prints lol
After spending time in the comments getting to the bottom of this question, I can confirm some of the details.
The Smarterer "answer" stating that just { MyProperty = 2 } was valid syntax for an anonymous type is only half correct. The syntax is required, but it is required in conjunction with the new keyword.
var anon = new { Name = "Adam", Age = 29 };
Attempting the following in VS 2012 will not compile:
// Try and make an anonymous type without new.
var anon = { Name = "Adam", Age = 29 };
// Try and declare an anonymous type prior to "newing" one up.
{ Name = "Adam", Age = 29 };
Again without the exact question and available answers from the other site, it is hard to provide context for the question and subsequent answer on this site. Hopefully this is enough to close it off.

conditional linq query behavior

I have a feeling the title is misleading, please edit if you choose to. when I do this:
var q = (condition)?(from ...Select(..)): (from.. Select(..));
I get a error at ":" saying
Type of conditional expression could not be determined because
there is no implicit conversion between anonymous types.
But if I do:
var b = some base linq query;
var q = (condition)?(use b here one way):(use b here differently);
no complaints. Why? How is second way different?
Edit:
Everywhere, my final projections are the same. (Final .Select(....) everywhere has same fields)
Edit2:
I apologize.. typo on my part. Select()s everywhere were not the same. Method 1 works fine too if the projections 'match'
It think the error message explains this:
Type of conditional expression could not be determined because
there is no implicit conversion between anonymous types.
This
var x = 0 < 2 ? new { a = 1 } : new { a = 2 }
would compile. but this
var x = 0 < 2 ? new { a = 1 } : new { b = 2 };
would give the error above because {a=1} and {b=2} are not the same anonymous types.
If you did a cast after your LINQ query everything would be fine.
Its sort of the same problem that you get then you do something like
int? val = true ? 1 : null;
That won't work, but if you cast the null like this:
int? val = true ? 1 : (int?)null;
It does.
A conditional expression needs the two operands it's evaluating to be the same type. So if you do
var a = (condition)? "A" : "B";
... both "A" and "B" are of the same type (string), so the result, a, will be of type string.
What your error message is telling you is that your two operands (the two from ... Select statements) evaluate to anonymous types, but not the same anonymous type, and it can't convert one anonymous type into another. Thus it doesn't know what type the result, q, should be.
While I am not 100% sure, I believe that even if your two expressions are exactly the same, they will be different anonymous types. At any rate, the fact that you got that error indicates that they are not the same anonymous type.
With your second set of statements, you first set b to be equal to the result of a linq query. Hence it has a type. Although your statement does say so, the fact that the code compiles implies that (use b here one way) and (use b here differently) return results of the same type. If they both return an instance of the same type as b, for example, they will be of the same type.

Passing IEnumerable data from LINQ as parameter to a method [duplicate]

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.

Trying to get array of custom object types from array of objects

I have a function that returns an array of objects. The problem is, the objects can be one of three different types. I am trying to break these objects into arrays of the different custom types.
For example:
var collection = something.ReturnObjArray();
var Details = collection.Where(a => a is DetailItem);
var Addenda = collection.Where(a => a is AddendaItem);
If i do the above and try to access the data in a foreach loop to put the Addenda in a collection within the Detail Items:
foreach (var addendaItem in Addenda)
{
var detailItem = Details.Single(d => d.DetailAddendaKey == addendaItem.Key);
detailItem.Addenda.Add(addendaItem);
}
I get errors like :
'object' does not contain a definition for 'DetailAddendaKey' and no extension method 'DetailAddendaKey' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
Among others. If i try and change the var for Details and Addenda to:
IEnumerable<DetailItem> Details = collection.Where(a => a is DetailItem);
IEnumerable<AddendaItem> Addenda = collection.Where(a => a is AddendaItem);
I get past the error above, but now get:
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<object>' to 'System.Collections.Generic.IEnumerable<MyNameSpace.DetailItem>'. An explicit conversion exists (are you missing a cast?)
Any ideas what I need to do?
Use OfType<T>.
Filters the elements of an IEnumerable based on a specified type.
Example:
IEnumerable<DetailItem> Details = collection.OfType<DetailItem>();
I suspect that this sentence returns an object of type object[] (an object array):
var collection = something.ReturnObjArray();
object doesn't have the whole properties!
That's why Details.Single(d => d.DetailAddendaKey == addendaItem.Key) complains about that d doesn't have a property DetailAddendaKey.
You need to do this:
var Details = collection.Where(a => a is DetailItem).Cast<DetailItem>();
var Addenda = collection.Where(a => a is AddendaItem).Cast<AddendaItem>();
Or as #Mark Byers suggested (which is an abbreviation of above sample):
var Details = collection.OfType<DetailItem>();
var Addenda = collection.OfType<AddendaItem>();
This is downcasting all items in the IEnumerable<object> to DetailItem or AddendaItem, meaning that you'll have an IEnumerable<DetailItem> and IEnumerable<AddendaItem> after all!
Then, the next sentences will compile and work as you expect.
Note
OfType<T>() should be a better choice since your approach of using is operator and later calling Cast<T>() is downcasting twice each object in the object array.
Check this other question and its answers for more info about is operator and its behavior:
C# 'is' operator performance

Categories