admin管理员组文章数量:1026989
TL;DR
If I want to cast from IEnumerable<T>
to System.Array<T>
without calling .ToArray()
, from IEnumerable<T>
to List<T>
without calling .ToList()
, etc. then what can I do if anything at all?
MINIMUM REPRODUCIBLE EXAMPLE
using System;
using System.Collections.Generic;
using System.Linq;
public class HelloWorld
{
public static void Main(string[] args)
{
string[] fruits = {"apple","mango","cherry"};
GenericTest(fruits, out var fruits_onlyApples);
}
private static void GenericTest<T>(T collection, out T alteredCollection) where T:class,IEnumerable<string>{
alteredCollection = (T)collection.Where(x=>x=="apple");
}
}
Hey guys, I'm trying to write a method like GenericTest<T>
above where, among other operations upon T
, I can use .Where()
from System.Linq
to filter the collection
into a copy by some predicate. The trouble is that, when the above code executes, I get an exception:
System.InvalidCastException: Specified cast is not valid.
I know what the problem is, this is because I'm doing a C-style cast from T
to string[]
when IEnumerable
specifically has the .ToArray()
method to achieve the transformation from IEnumerable
to System.Array
. Even though the return
type of .Where()
is the same as the generic type (T
) that goes into its predicate, one still has to cast to T
after using .Where()
or else the code simply won't compile. I presume one has to do the cast because the where
contracts used in the definition of .Where()
do not match the contracts used in my GenericTest<T>
method above.
What I want to know is what can I do about this? I don't want to call .ToArray()
directly because then that defeats the point of using a generic type and creates the problem I'm trying to avoid of making one method over and over doing pretty much the same thing but for List<>
, System.Array
, etc.
Any ideas? Many thanks for reading : )
TL;DR
If I want to cast from IEnumerable<T>
to System.Array<T>
without calling .ToArray()
, from IEnumerable<T>
to List<T>
without calling .ToList()
, etc. then what can I do if anything at all?
MINIMUM REPRODUCIBLE EXAMPLE
using System;
using System.Collections.Generic;
using System.Linq;
public class HelloWorld
{
public static void Main(string[] args)
{
string[] fruits = {"apple","mango","cherry"};
GenericTest(fruits, out var fruits_onlyApples);
}
private static void GenericTest<T>(T collection, out T alteredCollection) where T:class,IEnumerable<string>{
alteredCollection = (T)collection.Where(x=>x=="apple");
}
}
Hey guys, I'm trying to write a method like GenericTest<T>
above where, among other operations upon T
, I can use .Where()
from System.Linq
to filter the collection
into a copy by some predicate. The trouble is that, when the above code executes, I get an exception:
System.InvalidCastException: Specified cast is not valid.
I know what the problem is, this is because I'm doing a C-style cast from T
to string[]
when IEnumerable
specifically has the .ToArray()
method to achieve the transformation from IEnumerable
to System.Array
. Even though the return
type of .Where()
is the same as the generic type (T
) that goes into its predicate, one still has to cast to T
after using .Where()
or else the code simply won't compile. I presume one has to do the cast because the where
contracts used in the definition of .Where()
do not match the contracts used in my GenericTest<T>
method above.
What I want to know is what can I do about this? I don't want to call .ToArray()
directly because then that defeats the point of using a generic type and creates the problem I'm trying to avoid of making one method over and over doing pretty much the same thing but for List<>
, System.Array
, etc.
Any ideas? Many thanks for reading : )
Share Improve this question asked Dec 11, 2024 at 0:20 Spring E. ThingSpring E. Thing 1757 bronze badges 6 | Show 1 more comment1 Answer
Reset to default 2There are only a few limited cases where you can use .ToSomeCollection
or similar anyway. So you might as well special-case them.
private static void GenericTest<T>(T collection, out T alteredCollection) where T : class, IEnumerable<string>
{
var query = collection.Where(x => x == "apple");
if (typeof(T) == typeof(string[])
query = query.ToArray();
else if (typeof(T) == typeof(List<string>))
query = query.ToList();
else if (typeof(T) == typeof(HashSet<string>))
query = query.ToHashSet();
else
throw new UnsupportedException($"{typeof(T)} is unsupported");
alteredCollection = (T)query;
}
Alternatively just create some fixed overloads
private static void Test(string[] collection, out string[] alteredCollection)
{
var query = GenericTestCore(collection);
alteredCollection = query.ToArray();
}
private static void Test(List<string> collection, out List<string> alteredCollection)
{
var query = GenericTestCore(collection);
alteredCollection = query.ToList();
}
private static void Test(HashSet<string> collection, out HashSet<string> alteredCollection)
{
var query = GenericTestCore(collection);
alteredCollection = query.ToHashSet();
}
private static IEnumerable<string> GenericTestCore<T>(T collection) where T : class, IEnumerable<string>
{
return collection.Where(x => x == "apple");
}
Quite why you are using an out
parameter rather than a normal return
is not clear.
TL;DR
If I want to cast from IEnumerable<T>
to System.Array<T>
without calling .ToArray()
, from IEnumerable<T>
to List<T>
without calling .ToList()
, etc. then what can I do if anything at all?
MINIMUM REPRODUCIBLE EXAMPLE
using System;
using System.Collections.Generic;
using System.Linq;
public class HelloWorld
{
public static void Main(string[] args)
{
string[] fruits = {"apple","mango","cherry"};
GenericTest(fruits, out var fruits_onlyApples);
}
private static void GenericTest<T>(T collection, out T alteredCollection) where T:class,IEnumerable<string>{
alteredCollection = (T)collection.Where(x=>x=="apple");
}
}
Hey guys, I'm trying to write a method like GenericTest<T>
above where, among other operations upon T
, I can use .Where()
from System.Linq
to filter the collection
into a copy by some predicate. The trouble is that, when the above code executes, I get an exception:
System.InvalidCastException: Specified cast is not valid.
I know what the problem is, this is because I'm doing a C-style cast from T
to string[]
when IEnumerable
specifically has the .ToArray()
method to achieve the transformation from IEnumerable
to System.Array
. Even though the return
type of .Where()
is the same as the generic type (T
) that goes into its predicate, one still has to cast to T
after using .Where()
or else the code simply won't compile. I presume one has to do the cast because the where
contracts used in the definition of .Where()
do not match the contracts used in my GenericTest<T>
method above.
What I want to know is what can I do about this? I don't want to call .ToArray()
directly because then that defeats the point of using a generic type and creates the problem I'm trying to avoid of making one method over and over doing pretty much the same thing but for List<>
, System.Array
, etc.
Any ideas? Many thanks for reading : )
TL;DR
If I want to cast from IEnumerable<T>
to System.Array<T>
without calling .ToArray()
, from IEnumerable<T>
to List<T>
without calling .ToList()
, etc. then what can I do if anything at all?
MINIMUM REPRODUCIBLE EXAMPLE
using System;
using System.Collections.Generic;
using System.Linq;
public class HelloWorld
{
public static void Main(string[] args)
{
string[] fruits = {"apple","mango","cherry"};
GenericTest(fruits, out var fruits_onlyApples);
}
private static void GenericTest<T>(T collection, out T alteredCollection) where T:class,IEnumerable<string>{
alteredCollection = (T)collection.Where(x=>x=="apple");
}
}
Hey guys, I'm trying to write a method like GenericTest<T>
above where, among other operations upon T
, I can use .Where()
from System.Linq
to filter the collection
into a copy by some predicate. The trouble is that, when the above code executes, I get an exception:
System.InvalidCastException: Specified cast is not valid.
I know what the problem is, this is because I'm doing a C-style cast from T
to string[]
when IEnumerable
specifically has the .ToArray()
method to achieve the transformation from IEnumerable
to System.Array
. Even though the return
type of .Where()
is the same as the generic type (T
) that goes into its predicate, one still has to cast to T
after using .Where()
or else the code simply won't compile. I presume one has to do the cast because the where
contracts used in the definition of .Where()
do not match the contracts used in my GenericTest<T>
method above.
What I want to know is what can I do about this? I don't want to call .ToArray()
directly because then that defeats the point of using a generic type and creates the problem I'm trying to avoid of making one method over and over doing pretty much the same thing but for List<>
, System.Array
, etc.
Any ideas? Many thanks for reading : )
Share Improve this question asked Dec 11, 2024 at 0:20 Spring E. ThingSpring E. Thing 1757 bronze badges 6-
3
.Where()
is never going to returnT
, it returnsIEnumerable<string>
. You'd probably need to special case how to create each type, in which case I'd just overload the method instead of trying to implement this in a generic way. Or just make it the callers problem and just return theIEnumerable<string>
. – Jeremy Lakeman Commented Dec 11, 2024 at 0:25 -
@JeremyLakeman I had a feeling that's where this was going, I just figured since
T
andIEnumerable<string>
would always end up being the same type in the context of what I've written that there shouldn't be any issue but I guess not. Oh well, I will concede and just do overloads, thank you all the same! – Spring E. Thing Commented Dec 11, 2024 at 0:28 -
2
.Where
always returnsIEnumerable<T>
, neverList<T>
orT[]
. That would rather defeat the point of using enumerables. You call.ToList()
or.ToArray()
to materialise the items into an actual collection. – ProgrammingLlama Commented Dec 11, 2024 at 1:29 -
2
What is an actual real world use case for this? Why is it important that the result is the same collection type? This pattern seem to go against the whole idea of LINQ. Have you considered using an interface like
IReadOnlyList<T>
instead? That way you do not need to care if it is a list or an array. – JonasH Commented Dec 11, 2024 at 9:02 - "I want to cast from IEnumerable<T> to System.Array<T> without calling .ToArray()" - what makes you want that? I have the feeling it would be better to look at the underlying problem than fixing a sub-par solution to that. – Fildor Commented Dec 11, 2024 at 11:24
1 Answer
Reset to default 2There are only a few limited cases where you can use .ToSomeCollection
or similar anyway. So you might as well special-case them.
private static void GenericTest<T>(T collection, out T alteredCollection) where T : class, IEnumerable<string>
{
var query = collection.Where(x => x == "apple");
if (typeof(T) == typeof(string[])
query = query.ToArray();
else if (typeof(T) == typeof(List<string>))
query = query.ToList();
else if (typeof(T) == typeof(HashSet<string>))
query = query.ToHashSet();
else
throw new UnsupportedException($"{typeof(T)} is unsupported");
alteredCollection = (T)query;
}
Alternatively just create some fixed overloads
private static void Test(string[] collection, out string[] alteredCollection)
{
var query = GenericTestCore(collection);
alteredCollection = query.ToArray();
}
private static void Test(List<string> collection, out List<string> alteredCollection)
{
var query = GenericTestCore(collection);
alteredCollection = query.ToList();
}
private static void Test(HashSet<string> collection, out HashSet<string> alteredCollection)
{
var query = GenericTestCore(collection);
alteredCollection = query.ToHashSet();
}
private static IEnumerable<string> GenericTestCore<T>(T collection) where T : class, IEnumerable<string>
{
return collection.Where(x => x == "apple");
}
Quite why you are using an out
parameter rather than a normal return
is not clear.
本文标签: cCasting IEnumerableltTgt to Arraylistetc genericallyStack Overflow
版权声明:本文标题:c# - Casting IEnumerable<T> to Array, List, etc. generically? - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1736035577a1381780.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
.Where()
is never going to returnT
, it returnsIEnumerable<string>
. You'd probably need to special case how to create each type, in which case I'd just overload the method instead of trying to implement this in a generic way. Or just make it the callers problem and just return theIEnumerable<string>
. – Jeremy Lakeman Commented Dec 11, 2024 at 0:25T
andIEnumerable<string>
would always end up being the same type in the context of what I've written that there shouldn't be any issue but I guess not. Oh well, I will concede and just do overloads, thank you all the same! – Spring E. Thing Commented Dec 11, 2024 at 0:28.Where
always returnsIEnumerable<T>
, neverList<T>
orT[]
. That would rather defeat the point of using enumerables. You call.ToList()
or.ToArray()
to materialise the items into an actual collection. – ProgrammingLlama Commented Dec 11, 2024 at 1:29IReadOnlyList<T>
instead? That way you do not need to care if it is a list or an array. – JonasH Commented Dec 11, 2024 at 9:02