是否可以在编译时知道元素类型,而无需实现 IEnumerable 的类
本文关键字:实现 IEnumerable 的类 类型 编译 元素 是否 | 更新日期: 2023-09-27 17:50:09
-
总结
忽略对象不能表示为数组的情况,是否可以定义一个扩展(静态(方法,例如:
public static ? ToArray<TSource>(this TSource source);
并返回对象的数组,如果它由任何元素序列组成?如果是,
?
会是什么? -
解释
我想过以下声明:
public static TElement[] ToArray<TElement>(this IEnumerable<TElement> source); public static ? ToArray<TSource>(this IEnumerable source);
但我不能假设一个未知的类一定实现了
IEnumerable<T>
或IEnumerable
。我什至无法定义?
,因为它只是IEnumerable
,超出了通用定义。我也想到了
Array
类:public static Array ToArray<TSource>(this TSource source);
但这意味着元素类型在编译时是未知的。
所以我想知道是否可以在没有类实现
IEnumerable<T>
的情况下在编译时知道元素类型?
不幸的是,IEnumerator
早于泛型,因此它不携带任何类型信息; 只是一个IEnumerator GetEnumerator()
,使String
不那么吸引人尝试并强制进入您正在尝试完成的这个通用实现。
我已经很久没有做过 C# 了,但我想:
public static TElement ToArray<TSource>(this IEnumerable<TElement> source);
。应该没问题,因为:
public static TElement[] ToArray<TElement>(this IEnumerable<TElement> source);
关于扩展方法,要记住的重要一点是它们只是语法糖。它们实际上不会留下来或被注入到他们正在装饰的类型中。它们在编译时被替换为静态方法调用。您使用延长方式的里程会有所不同。
你的问题具体是什么? 如果你问IEnumerable
中的元素类型在编译时是否总是已知的,那么答案是"不,它并不总是已知的"。非泛型 IEnumerable 不强制任何元素类型。这就是为什么你可以在任何IEnumerable
上定义一个foreach
循环:
IEnumerable items = GetItems();
foreach(SomeClass item in items)
{
...
}
但是,如果items
元素之一无法转换为SomeClass
,这将引发InvalidCastException
。
顺便说一下,如果您定义如下方法:
public static TElement[] MyToArray<TElement>(this IEnumerable<TElement> source);
然后,可以在 .NET 2.0+ 中的string
上调用它,因为string
在 .NET 2.0 和 3.0 中实现IEnumerable<string>
,在 3.5+ 中实现IEnumerable<char>
。 事实上,内置于 .NET 中的 .ToArray()
扩展已经可以在string
上使用,而无需定义任何内容。
它在编译时是未知的,也不可能是已知的。
例如,我可以做:
IEnumerable myCollection;
string discriminator = Console.ReadLine();
if (discriminator == "string")
{
myCollection = new List<string>{"One", "Two", "Three", "Four"};
}
else
{
myCollection = new int[]{1, 2, 3, 4};
}
//what should be the type of the elements variable
var elements = myCollection.ToArray();
基本上,根据用户输入,myCollection
将是 List<string>
或int[]
,这两种类型除了可枚举之外几乎没有任何共同点。
因此,为了使ToArray
方法正常工作,可以使用IEnumerable<T>
而不是IEnumerable
引入类型安全和泛型,也可以使用对象集合(如object[]
(作为方法的返回类型。