Generic casting in linq request

So, I have a class that takes a parameter of a general type and does a little special processing if the type parameter is a subclass of the given type.

IEnumerable<T> models = ... // Special handling of MySpecialModel if (filterString != null && typeof(MySpecialModel).IsAssignableFrom(typeof(T))) { var filters = filterString.Split(...); models = from m in models.Cast<MySpecialModel>() where (from t in m.Tags from f in filters where t.IndexOf(f, StringComparison.CurrentCultureIgnoreCase) >= 0 select t) .Any() select (T)m; } 

But I get an exception in the last line

 Cannot convert type 'MySpecialModel' to 'T' 

If I changed the code to use as instead of casting, I get this error.

 The type parameter 'T' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint. 

What am I missing here?

Update

This class can accept any type parameter, including struct and built-in types, so a general constraint would not be a suitable solution in my case.

+6
source share
6 answers

Make Select(x => (MySpecialModel)x)

The LINQ Cast<T> method will only work to distinguish elements from the element that already exists (for example, a base type, derived type, or interface). It is not intended to create objects that can be selected for the target type. (for example, new List<int>{1,2,3}.Cast<long>() also throws an exception.

The above answer was not wrong, but it does not address the question.

Just because you proved with the reflection that the general parameter is bound to this type does not mean that the compiler knows that it is. To do this, you will need to give your T instance a generic type (e.g. object ), and then apply it to a specific type. for example (changing the last line in a query to select (T)(object)m should do the trick.

+3
source

Try to execute

 select (T)(object)m; 

At run time, you confirmed that T is a subtype of MySpecialModel , but the compiler does not have access to this information at compile time. He just sees an attempt to convert between two unrelated types: T and MySpecialModel .

To get around this, you need to use object as the average person. The compiler understands how to convert MySpecialModel to object and switch from object to T

+2
source

To use the as keyword, put a class constraint on your generic parameter:

 void MyMethod<T>(T item) where T : class { //... } 
+1
source

If you know that a generic type will always be a class, you can add a type constraint to your class:

 public class Test<T> where T : class {} 

Otherwise, double cast through the object, as smartcaveman suggested:

 .Select(x => (T)(object)x); 
+1
source

The most direct fix is โ€‹โ€‹to distinguish to object before casting to T :

 select (T)(object)m; 

The problem is that your check occurs at run time, but the compiler does not know that T should be an instance of MySpecialModel in the if . Therefore, it just sees that you are trying to pass an arbitrary type T from MySpecialModel , which is unsafe, hence an error.

+1
source

You can apply the Nullable<T> constraint, which should include the possibility of use (at least using a "how").

0
source

All Articles