Relation between List and IEnumerable open type
up vote
15
down vote
favorite
Is there any relationship between the open types List<>
and IEnumerable<>
?
Example:
var type1 = typeof(List<>);
var type2 = typeof(IEnumerable<>);
//return false
type2.IsAssignableFrom(type1);
Is there any method to check the relationship between two open type, or the relationship only exist on closed type?
c# .net
|
show 2 more comments
up vote
15
down vote
favorite
Is there any relationship between the open types List<>
and IEnumerable<>
?
Example:
var type1 = typeof(List<>);
var type2 = typeof(IEnumerable<>);
//return false
type2.IsAssignableFrom(type1);
Is there any method to check the relationship between two open type, or the relationship only exist on closed type?
c# .net
Relevant: When does Type.FullName return null?
– John Wu
Nov 20 at 7:16
1
Note that each generic parameter is unique. That meansList<T(from List<T>)>
implementIEnumerable<T(from List<T>)>
but notIEnumerable<T(from IEnumerable<T>)>
.
– PetSerAl
Nov 20 at 7:22
3
What are you actually trying to accomplish here? If we knew what the initial problem you were trying to solve was, we may be able to offer other solutions that don't rely on comparing open generic types.
– Damien_The_Unbeliever
Nov 20 at 7:59
Sorry for the drastic edit, but I think only the problem expressed in the first 3 lines is the actually interesting part here. What you were trying to do with the rest of the code was very unclear and you would have had to explain that further as @Damien_The_Unbeliever stated.
– marsze
Nov 20 at 9:34
@PetSerAl How to understand each generic parameter is unique? Do you mean type int in List<int> and IEnumerable<int> is "diffierent"?
– YonF
Nov 21 at 3:12
|
show 2 more comments
up vote
15
down vote
favorite
up vote
15
down vote
favorite
Is there any relationship between the open types List<>
and IEnumerable<>
?
Example:
var type1 = typeof(List<>);
var type2 = typeof(IEnumerable<>);
//return false
type2.IsAssignableFrom(type1);
Is there any method to check the relationship between two open type, or the relationship only exist on closed type?
c# .net
Is there any relationship between the open types List<>
and IEnumerable<>
?
Example:
var type1 = typeof(List<>);
var type2 = typeof(IEnumerable<>);
//return false
type2.IsAssignableFrom(type1);
Is there any method to check the relationship between two open type, or the relationship only exist on closed type?
c# .net
c# .net
edited Nov 20 at 9:31
marsze
4,14131640
4,14131640
asked Nov 20 at 7:04
YonF
18610
18610
Relevant: When does Type.FullName return null?
– John Wu
Nov 20 at 7:16
1
Note that each generic parameter is unique. That meansList<T(from List<T>)>
implementIEnumerable<T(from List<T>)>
but notIEnumerable<T(from IEnumerable<T>)>
.
– PetSerAl
Nov 20 at 7:22
3
What are you actually trying to accomplish here? If we knew what the initial problem you were trying to solve was, we may be able to offer other solutions that don't rely on comparing open generic types.
– Damien_The_Unbeliever
Nov 20 at 7:59
Sorry for the drastic edit, but I think only the problem expressed in the first 3 lines is the actually interesting part here. What you were trying to do with the rest of the code was very unclear and you would have had to explain that further as @Damien_The_Unbeliever stated.
– marsze
Nov 20 at 9:34
@PetSerAl How to understand each generic parameter is unique? Do you mean type int in List<int> and IEnumerable<int> is "diffierent"?
– YonF
Nov 21 at 3:12
|
show 2 more comments
Relevant: When does Type.FullName return null?
– John Wu
Nov 20 at 7:16
1
Note that each generic parameter is unique. That meansList<T(from List<T>)>
implementIEnumerable<T(from List<T>)>
but notIEnumerable<T(from IEnumerable<T>)>
.
– PetSerAl
Nov 20 at 7:22
3
What are you actually trying to accomplish here? If we knew what the initial problem you were trying to solve was, we may be able to offer other solutions that don't rely on comparing open generic types.
– Damien_The_Unbeliever
Nov 20 at 7:59
Sorry for the drastic edit, but I think only the problem expressed in the first 3 lines is the actually interesting part here. What you were trying to do with the rest of the code was very unclear and you would have had to explain that further as @Damien_The_Unbeliever stated.
– marsze
Nov 20 at 9:34
@PetSerAl How to understand each generic parameter is unique? Do you mean type int in List<int> and IEnumerable<int> is "diffierent"?
– YonF
Nov 21 at 3:12
Relevant: When does Type.FullName return null?
– John Wu
Nov 20 at 7:16
Relevant: When does Type.FullName return null?
– John Wu
Nov 20 at 7:16
1
1
Note that each generic parameter is unique. That means
List<T(from List<T>)>
implement IEnumerable<T(from List<T>)>
but not IEnumerable<T(from IEnumerable<T>)>
.– PetSerAl
Nov 20 at 7:22
Note that each generic parameter is unique. That means
List<T(from List<T>)>
implement IEnumerable<T(from List<T>)>
but not IEnumerable<T(from IEnumerable<T>)>
.– PetSerAl
Nov 20 at 7:22
3
3
What are you actually trying to accomplish here? If we knew what the initial problem you were trying to solve was, we may be able to offer other solutions that don't rely on comparing open generic types.
– Damien_The_Unbeliever
Nov 20 at 7:59
What are you actually trying to accomplish here? If we knew what the initial problem you were trying to solve was, we may be able to offer other solutions that don't rely on comparing open generic types.
– Damien_The_Unbeliever
Nov 20 at 7:59
Sorry for the drastic edit, but I think only the problem expressed in the first 3 lines is the actually interesting part here. What you were trying to do with the rest of the code was very unclear and you would have had to explain that further as @Damien_The_Unbeliever stated.
– marsze
Nov 20 at 9:34
Sorry for the drastic edit, but I think only the problem expressed in the first 3 lines is the actually interesting part here. What you were trying to do with the rest of the code was very unclear and you would have had to explain that further as @Damien_The_Unbeliever stated.
– marsze
Nov 20 at 9:34
@PetSerAl How to understand each generic parameter is unique? Do you mean type int in List<int> and IEnumerable<int> is "diffierent"?
– YonF
Nov 21 at 3:12
@PetSerAl How to understand each generic parameter is unique? Do you mean type int in List<int> and IEnumerable<int> is "diffierent"?
– YonF
Nov 21 at 3:12
|
show 2 more comments
2 Answers
2
active
oldest
votes
up vote
16
down vote
List<>
and IEnumerable<>
are not types; they are type definitions. As such it doesn't really make sense to ask if one is assignable to the other. Neither can be assigned to. You can't declare a variable List<> a = null
, for example-- you will get a compilation error "Unexpected use of an unbound generic name."
A type definition becomes a generic type when you specify the type parameter. At that point, it is a type and can be assigned to. So for example List<string>
can be assigned to IEnumerable<string>
.
If you have a type definition in mind and you want to do a type-compatibility check, just use <object>
(or a suitable type if there is a type constraint) instead of <>
:
var type1 = typeof(List<object>);
var type2 = typeof(IEnumerable<object>);
//returns true
type2.IsAssignableFrom(type1);
Thanks for your answer. It is a brief check method. I can understandtype2.IsAssignableFrom(type1)
behavior. But do you mean two open generic type are independent or no relationship between them before they become closed type or bounded?
– YonF
Nov 21 at 5:32
Can you be specific about what you mean when you say "related?" Of course they have certain relationships, and not others.
– John Wu
Nov 21 at 6:38
A relationship such as inheritance, implimentation but not inheritance and implimentation. But I am not sure whether any kind relatioinship exist between open generic type themselves. @Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
– YonF
Nov 21 at 7:07
Believe it or not, generic type definitions do not have any implementation. The implementation is compiled only when you specify the type parameter, and only for that type (although implementations for reference types can be re-used because all pointers are the same size, but that is just an implementation detail). So you see to ask whetherList<>
implementsIEnumerable<>
doesn't make much sense because it has no implementation to begin with.
– John Wu
Nov 21 at 7:15
@Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
Oh but it is most definitely there in the framework code, so the relation exists, but as long as it doesn't have a concrete implementation, its useless, as John Wu pointed out.
– Jevgeni Geurtsen
Nov 21 at 8:16
add a comment |
up vote
13
down vote
Although John Wu wrote up a nice answer about the differences between a type definition and actual types I don't think it fully answers the problem/question asked in the OP.
Is there any method to check the relationship between two open type,
or the relationship only exist on closed type?
First of all, the relationship always exists; every List<>
is always an IEnumerable<>
, as you can see in the definition of the List<T>
type:
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, ...
But this doesn't answer your second question, if there is a way to check if such a relationship exists between two types. You would think that the IsAssignableFrom
method can be used to check for existence of a relationship between the type open types, but you can't. Why? Lets find out in the documentation of the IsAssignableFrom
function:
Type.IsAssignableFrom (Type c) Returns true if any of the following conditions is true:
- c and the current instance represent the same type.
c is derived either directly or indirectly from the current
instance. c is derived directly from the current instance if it
inherits from the current instance; c is derived indirectly from the
current instance if it inherits from a succession of one or more
classes that inherit from the current instance.
The current instance is an interface that c implements.
c is a generic type parameter, and the current instance represents
one of the constraints of c.
and false if none of these conditions are true, or if c is null.
In your case, none of the above mentioned conditions will result in true as: (1) they are not the same type. (2) They cannot be derived from each other as they are open types: their generic type parameters are unknown (unknown != unknown
). The List<>
implements the closed IEnumerable<T>
type and not the open IEnumerable<>
type (3). They aren't generic type parameters (4).
To find out if two generic types have a relationship, you would need to inspect their type definitions
(and their nested interfaces/base types) and validate that they have a relationship:
public static bool IsAssignableToOpenGenericType(Type givenType, Type genericType)
{
var interfaceTypes = givenType.GetInterfaces();
foreach (var it in interfaceTypes)
{
if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
return true;
}
if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
return true;
Type baseType = givenType.BaseType;
if (baseType == null) return false;
return IsAssignableToGenericType(baseType, genericType);
}
(source)
Will result in:
var typ1 = typeof(List<>);
var typ2 = typeof(IEnumerable<>);
// true, List<>'s type definition contains an IEnumerable<>
Console.WriteLine(IsAssignableToOpenGenericType(typ1, typ2));
// false, IEnumerable<>'s type definition does not contain List<>
Console.WriteLine(IsAssignableToOpenGenericType(typ2, typ1));
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
16
down vote
List<>
and IEnumerable<>
are not types; they are type definitions. As such it doesn't really make sense to ask if one is assignable to the other. Neither can be assigned to. You can't declare a variable List<> a = null
, for example-- you will get a compilation error "Unexpected use of an unbound generic name."
A type definition becomes a generic type when you specify the type parameter. At that point, it is a type and can be assigned to. So for example List<string>
can be assigned to IEnumerable<string>
.
If you have a type definition in mind and you want to do a type-compatibility check, just use <object>
(or a suitable type if there is a type constraint) instead of <>
:
var type1 = typeof(List<object>);
var type2 = typeof(IEnumerable<object>);
//returns true
type2.IsAssignableFrom(type1);
Thanks for your answer. It is a brief check method. I can understandtype2.IsAssignableFrom(type1)
behavior. But do you mean two open generic type are independent or no relationship between them before they become closed type or bounded?
– YonF
Nov 21 at 5:32
Can you be specific about what you mean when you say "related?" Of course they have certain relationships, and not others.
– John Wu
Nov 21 at 6:38
A relationship such as inheritance, implimentation but not inheritance and implimentation. But I am not sure whether any kind relatioinship exist between open generic type themselves. @Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
– YonF
Nov 21 at 7:07
Believe it or not, generic type definitions do not have any implementation. The implementation is compiled only when you specify the type parameter, and only for that type (although implementations for reference types can be re-used because all pointers are the same size, but that is just an implementation detail). So you see to ask whetherList<>
implementsIEnumerable<>
doesn't make much sense because it has no implementation to begin with.
– John Wu
Nov 21 at 7:15
@Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
Oh but it is most definitely there in the framework code, so the relation exists, but as long as it doesn't have a concrete implementation, its useless, as John Wu pointed out.
– Jevgeni Geurtsen
Nov 21 at 8:16
add a comment |
up vote
16
down vote
List<>
and IEnumerable<>
are not types; they are type definitions. As such it doesn't really make sense to ask if one is assignable to the other. Neither can be assigned to. You can't declare a variable List<> a = null
, for example-- you will get a compilation error "Unexpected use of an unbound generic name."
A type definition becomes a generic type when you specify the type parameter. At that point, it is a type and can be assigned to. So for example List<string>
can be assigned to IEnumerable<string>
.
If you have a type definition in mind and you want to do a type-compatibility check, just use <object>
(or a suitable type if there is a type constraint) instead of <>
:
var type1 = typeof(List<object>);
var type2 = typeof(IEnumerable<object>);
//returns true
type2.IsAssignableFrom(type1);
Thanks for your answer. It is a brief check method. I can understandtype2.IsAssignableFrom(type1)
behavior. But do you mean two open generic type are independent or no relationship between them before they become closed type or bounded?
– YonF
Nov 21 at 5:32
Can you be specific about what you mean when you say "related?" Of course they have certain relationships, and not others.
– John Wu
Nov 21 at 6:38
A relationship such as inheritance, implimentation but not inheritance and implimentation. But I am not sure whether any kind relatioinship exist between open generic type themselves. @Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
– YonF
Nov 21 at 7:07
Believe it or not, generic type definitions do not have any implementation. The implementation is compiled only when you specify the type parameter, and only for that type (although implementations for reference types can be re-used because all pointers are the same size, but that is just an implementation detail). So you see to ask whetherList<>
implementsIEnumerable<>
doesn't make much sense because it has no implementation to begin with.
– John Wu
Nov 21 at 7:15
@Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
Oh but it is most definitely there in the framework code, so the relation exists, but as long as it doesn't have a concrete implementation, its useless, as John Wu pointed out.
– Jevgeni Geurtsen
Nov 21 at 8:16
add a comment |
up vote
16
down vote
up vote
16
down vote
List<>
and IEnumerable<>
are not types; they are type definitions. As such it doesn't really make sense to ask if one is assignable to the other. Neither can be assigned to. You can't declare a variable List<> a = null
, for example-- you will get a compilation error "Unexpected use of an unbound generic name."
A type definition becomes a generic type when you specify the type parameter. At that point, it is a type and can be assigned to. So for example List<string>
can be assigned to IEnumerable<string>
.
If you have a type definition in mind and you want to do a type-compatibility check, just use <object>
(or a suitable type if there is a type constraint) instead of <>
:
var type1 = typeof(List<object>);
var type2 = typeof(IEnumerable<object>);
//returns true
type2.IsAssignableFrom(type1);
List<>
and IEnumerable<>
are not types; they are type definitions. As such it doesn't really make sense to ask if one is assignable to the other. Neither can be assigned to. You can't declare a variable List<> a = null
, for example-- you will get a compilation error "Unexpected use of an unbound generic name."
A type definition becomes a generic type when you specify the type parameter. At that point, it is a type and can be assigned to. So for example List<string>
can be assigned to IEnumerable<string>
.
If you have a type definition in mind and you want to do a type-compatibility check, just use <object>
(or a suitable type if there is a type constraint) instead of <>
:
var type1 = typeof(List<object>);
var type2 = typeof(IEnumerable<object>);
//returns true
type2.IsAssignableFrom(type1);
edited Nov 20 at 11:46
vaxquis
7,37653656
7,37653656
answered Nov 20 at 8:42
John Wu
28.9k42652
28.9k42652
Thanks for your answer. It is a brief check method. I can understandtype2.IsAssignableFrom(type1)
behavior. But do you mean two open generic type are independent or no relationship between them before they become closed type or bounded?
– YonF
Nov 21 at 5:32
Can you be specific about what you mean when you say "related?" Of course they have certain relationships, and not others.
– John Wu
Nov 21 at 6:38
A relationship such as inheritance, implimentation but not inheritance and implimentation. But I am not sure whether any kind relatioinship exist between open generic type themselves. @Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
– YonF
Nov 21 at 7:07
Believe it or not, generic type definitions do not have any implementation. The implementation is compiled only when you specify the type parameter, and only for that type (although implementations for reference types can be re-used because all pointers are the same size, but that is just an implementation detail). So you see to ask whetherList<>
implementsIEnumerable<>
doesn't make much sense because it has no implementation to begin with.
– John Wu
Nov 21 at 7:15
@Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
Oh but it is most definitely there in the framework code, so the relation exists, but as long as it doesn't have a concrete implementation, its useless, as John Wu pointed out.
– Jevgeni Geurtsen
Nov 21 at 8:16
add a comment |
Thanks for your answer. It is a brief check method. I can understandtype2.IsAssignableFrom(type1)
behavior. But do you mean two open generic type are independent or no relationship between them before they become closed type or bounded?
– YonF
Nov 21 at 5:32
Can you be specific about what you mean when you say "related?" Of course they have certain relationships, and not others.
– John Wu
Nov 21 at 6:38
A relationship such as inheritance, implimentation but not inheritance and implimentation. But I am not sure whether any kind relatioinship exist between open generic type themselves. @Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
– YonF
Nov 21 at 7:07
Believe it or not, generic type definitions do not have any implementation. The implementation is compiled only when you specify the type parameter, and only for that type (although implementations for reference types can be re-used because all pointers are the same size, but that is just an implementation detail). So you see to ask whetherList<>
implementsIEnumerable<>
doesn't make much sense because it has no implementation to begin with.
– John Wu
Nov 21 at 7:15
@Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
Oh but it is most definitely there in the framework code, so the relation exists, but as long as it doesn't have a concrete implementation, its useless, as John Wu pointed out.
– Jevgeni Geurtsen
Nov 21 at 8:16
Thanks for your answer. It is a brief check method. I can understand
type2.IsAssignableFrom(type1)
behavior. But do you mean two open generic type are independent or no relationship between them before they become closed type or bounded?– YonF
Nov 21 at 5:32
Thanks for your answer. It is a brief check method. I can understand
type2.IsAssignableFrom(type1)
behavior. But do you mean two open generic type are independent or no relationship between them before they become closed type or bounded?– YonF
Nov 21 at 5:32
Can you be specific about what you mean when you say "related?" Of course they have certain relationships, and not others.
– John Wu
Nov 21 at 6:38
Can you be specific about what you mean when you say "related?" Of course they have certain relationships, and not others.
– John Wu
Nov 21 at 6:38
A relationship such as inheritance, implimentation but not inheritance and implimentation. But I am not sure whether any kind relatioinship exist between open generic type themselves. @Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
– YonF
Nov 21 at 7:07
A relationship such as inheritance, implimentation but not inheritance and implimentation. But I am not sure whether any kind relatioinship exist between open generic type themselves. @Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
– YonF
Nov 21 at 7:07
Believe it or not, generic type definitions do not have any implementation. The implementation is compiled only when you specify the type parameter, and only for that type (although implementations for reference types can be re-used because all pointers are the same size, but that is just an implementation detail). So you see to ask whether
List<>
implements IEnumerable<>
doesn't make much sense because it has no implementation to begin with.– John Wu
Nov 21 at 7:15
Believe it or not, generic type definitions do not have any implementation. The implementation is compiled only when you specify the type parameter, and only for that type (although implementations for reference types can be re-used because all pointers are the same size, but that is just an implementation detail). So you see to ask whether
List<>
implements IEnumerable<>
doesn't make much sense because it has no implementation to begin with.– John Wu
Nov 21 at 7:15
@Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
Oh but it is most definitely there in the framework code, so the relation exists, but as long as it doesn't have a concrete implementation, its useless, as John Wu pointed out.– Jevgeni Geurtsen
Nov 21 at 8:16
@Jevgeni Geurtsen think the special relationship list AssignableFrom exist.
Oh but it is most definitely there in the framework code, so the relation exists, but as long as it doesn't have a concrete implementation, its useless, as John Wu pointed out.– Jevgeni Geurtsen
Nov 21 at 8:16
add a comment |
up vote
13
down vote
Although John Wu wrote up a nice answer about the differences between a type definition and actual types I don't think it fully answers the problem/question asked in the OP.
Is there any method to check the relationship between two open type,
or the relationship only exist on closed type?
First of all, the relationship always exists; every List<>
is always an IEnumerable<>
, as you can see in the definition of the List<T>
type:
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, ...
But this doesn't answer your second question, if there is a way to check if such a relationship exists between two types. You would think that the IsAssignableFrom
method can be used to check for existence of a relationship between the type open types, but you can't. Why? Lets find out in the documentation of the IsAssignableFrom
function:
Type.IsAssignableFrom (Type c) Returns true if any of the following conditions is true:
- c and the current instance represent the same type.
c is derived either directly or indirectly from the current
instance. c is derived directly from the current instance if it
inherits from the current instance; c is derived indirectly from the
current instance if it inherits from a succession of one or more
classes that inherit from the current instance.
The current instance is an interface that c implements.
c is a generic type parameter, and the current instance represents
one of the constraints of c.
and false if none of these conditions are true, or if c is null.
In your case, none of the above mentioned conditions will result in true as: (1) they are not the same type. (2) They cannot be derived from each other as they are open types: their generic type parameters are unknown (unknown != unknown
). The List<>
implements the closed IEnumerable<T>
type and not the open IEnumerable<>
type (3). They aren't generic type parameters (4).
To find out if two generic types have a relationship, you would need to inspect their type definitions
(and their nested interfaces/base types) and validate that they have a relationship:
public static bool IsAssignableToOpenGenericType(Type givenType, Type genericType)
{
var interfaceTypes = givenType.GetInterfaces();
foreach (var it in interfaceTypes)
{
if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
return true;
}
if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
return true;
Type baseType = givenType.BaseType;
if (baseType == null) return false;
return IsAssignableToGenericType(baseType, genericType);
}
(source)
Will result in:
var typ1 = typeof(List<>);
var typ2 = typeof(IEnumerable<>);
// true, List<>'s type definition contains an IEnumerable<>
Console.WriteLine(IsAssignableToOpenGenericType(typ1, typ2));
// false, IEnumerable<>'s type definition does not contain List<>
Console.WriteLine(IsAssignableToOpenGenericType(typ2, typ1));
add a comment |
up vote
13
down vote
Although John Wu wrote up a nice answer about the differences between a type definition and actual types I don't think it fully answers the problem/question asked in the OP.
Is there any method to check the relationship between two open type,
or the relationship only exist on closed type?
First of all, the relationship always exists; every List<>
is always an IEnumerable<>
, as you can see in the definition of the List<T>
type:
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, ...
But this doesn't answer your second question, if there is a way to check if such a relationship exists between two types. You would think that the IsAssignableFrom
method can be used to check for existence of a relationship between the type open types, but you can't. Why? Lets find out in the documentation of the IsAssignableFrom
function:
Type.IsAssignableFrom (Type c) Returns true if any of the following conditions is true:
- c and the current instance represent the same type.
c is derived either directly or indirectly from the current
instance. c is derived directly from the current instance if it
inherits from the current instance; c is derived indirectly from the
current instance if it inherits from a succession of one or more
classes that inherit from the current instance.
The current instance is an interface that c implements.
c is a generic type parameter, and the current instance represents
one of the constraints of c.
and false if none of these conditions are true, or if c is null.
In your case, none of the above mentioned conditions will result in true as: (1) they are not the same type. (2) They cannot be derived from each other as they are open types: their generic type parameters are unknown (unknown != unknown
). The List<>
implements the closed IEnumerable<T>
type and not the open IEnumerable<>
type (3). They aren't generic type parameters (4).
To find out if two generic types have a relationship, you would need to inspect their type definitions
(and their nested interfaces/base types) and validate that they have a relationship:
public static bool IsAssignableToOpenGenericType(Type givenType, Type genericType)
{
var interfaceTypes = givenType.GetInterfaces();
foreach (var it in interfaceTypes)
{
if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
return true;
}
if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
return true;
Type baseType = givenType.BaseType;
if (baseType == null) return false;
return IsAssignableToGenericType(baseType, genericType);
}
(source)
Will result in:
var typ1 = typeof(List<>);
var typ2 = typeof(IEnumerable<>);
// true, List<>'s type definition contains an IEnumerable<>
Console.WriteLine(IsAssignableToOpenGenericType(typ1, typ2));
// false, IEnumerable<>'s type definition does not contain List<>
Console.WriteLine(IsAssignableToOpenGenericType(typ2, typ1));
add a comment |
up vote
13
down vote
up vote
13
down vote
Although John Wu wrote up a nice answer about the differences between a type definition and actual types I don't think it fully answers the problem/question asked in the OP.
Is there any method to check the relationship between two open type,
or the relationship only exist on closed type?
First of all, the relationship always exists; every List<>
is always an IEnumerable<>
, as you can see in the definition of the List<T>
type:
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, ...
But this doesn't answer your second question, if there is a way to check if such a relationship exists between two types. You would think that the IsAssignableFrom
method can be used to check for existence of a relationship between the type open types, but you can't. Why? Lets find out in the documentation of the IsAssignableFrom
function:
Type.IsAssignableFrom (Type c) Returns true if any of the following conditions is true:
- c and the current instance represent the same type.
c is derived either directly or indirectly from the current
instance. c is derived directly from the current instance if it
inherits from the current instance; c is derived indirectly from the
current instance if it inherits from a succession of one or more
classes that inherit from the current instance.
The current instance is an interface that c implements.
c is a generic type parameter, and the current instance represents
one of the constraints of c.
and false if none of these conditions are true, or if c is null.
In your case, none of the above mentioned conditions will result in true as: (1) they are not the same type. (2) They cannot be derived from each other as they are open types: their generic type parameters are unknown (unknown != unknown
). The List<>
implements the closed IEnumerable<T>
type and not the open IEnumerable<>
type (3). They aren't generic type parameters (4).
To find out if two generic types have a relationship, you would need to inspect their type definitions
(and their nested interfaces/base types) and validate that they have a relationship:
public static bool IsAssignableToOpenGenericType(Type givenType, Type genericType)
{
var interfaceTypes = givenType.GetInterfaces();
foreach (var it in interfaceTypes)
{
if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
return true;
}
if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
return true;
Type baseType = givenType.BaseType;
if (baseType == null) return false;
return IsAssignableToGenericType(baseType, genericType);
}
(source)
Will result in:
var typ1 = typeof(List<>);
var typ2 = typeof(IEnumerable<>);
// true, List<>'s type definition contains an IEnumerable<>
Console.WriteLine(IsAssignableToOpenGenericType(typ1, typ2));
// false, IEnumerable<>'s type definition does not contain List<>
Console.WriteLine(IsAssignableToOpenGenericType(typ2, typ1));
Although John Wu wrote up a nice answer about the differences between a type definition and actual types I don't think it fully answers the problem/question asked in the OP.
Is there any method to check the relationship between two open type,
or the relationship only exist on closed type?
First of all, the relationship always exists; every List<>
is always an IEnumerable<>
, as you can see in the definition of the List<T>
type:
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, ...
But this doesn't answer your second question, if there is a way to check if such a relationship exists between two types. You would think that the IsAssignableFrom
method can be used to check for existence of a relationship between the type open types, but you can't. Why? Lets find out in the documentation of the IsAssignableFrom
function:
Type.IsAssignableFrom (Type c) Returns true if any of the following conditions is true:
- c and the current instance represent the same type.
c is derived either directly or indirectly from the current
instance. c is derived directly from the current instance if it
inherits from the current instance; c is derived indirectly from the
current instance if it inherits from a succession of one or more
classes that inherit from the current instance.
The current instance is an interface that c implements.
c is a generic type parameter, and the current instance represents
one of the constraints of c.
and false if none of these conditions are true, or if c is null.
In your case, none of the above mentioned conditions will result in true as: (1) they are not the same type. (2) They cannot be derived from each other as they are open types: their generic type parameters are unknown (unknown != unknown
). The List<>
implements the closed IEnumerable<T>
type and not the open IEnumerable<>
type (3). They aren't generic type parameters (4).
To find out if two generic types have a relationship, you would need to inspect their type definitions
(and their nested interfaces/base types) and validate that they have a relationship:
public static bool IsAssignableToOpenGenericType(Type givenType, Type genericType)
{
var interfaceTypes = givenType.GetInterfaces();
foreach (var it in interfaceTypes)
{
if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
return true;
}
if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
return true;
Type baseType = givenType.BaseType;
if (baseType == null) return false;
return IsAssignableToGenericType(baseType, genericType);
}
(source)
Will result in:
var typ1 = typeof(List<>);
var typ2 = typeof(IEnumerable<>);
// true, List<>'s type definition contains an IEnumerable<>
Console.WriteLine(IsAssignableToOpenGenericType(typ1, typ2));
// false, IEnumerable<>'s type definition does not contain List<>
Console.WriteLine(IsAssignableToOpenGenericType(typ2, typ1));
edited Nov 20 at 10:39
answered Nov 20 at 9:11
Jevgeni Geurtsen
2,54641231
2,54641231
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53387828%2frelation-between-list-and-ienumerable-open-type%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Relevant: When does Type.FullName return null?
– John Wu
Nov 20 at 7:16
1
Note that each generic parameter is unique. That means
List<T(from List<T>)>
implementIEnumerable<T(from List<T>)>
but notIEnumerable<T(from IEnumerable<T>)>
.– PetSerAl
Nov 20 at 7:22
3
What are you actually trying to accomplish here? If we knew what the initial problem you were trying to solve was, we may be able to offer other solutions that don't rely on comparing open generic types.
– Damien_The_Unbeliever
Nov 20 at 7:59
Sorry for the drastic edit, but I think only the problem expressed in the first 3 lines is the actually interesting part here. What you were trying to do with the rest of the code was very unclear and you would have had to explain that further as @Damien_The_Unbeliever stated.
– marsze
Nov 20 at 9:34
@PetSerAl How to understand each generic parameter is unique? Do you mean type int in List<int> and IEnumerable<int> is "diffierent"?
– YonF
Nov 21 at 3:12