是否可以在编译时知道元素类型,而无需实现 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>的情况下在编译时知道元素类型?

是否可以在编译时知道元素类型,而无需实现 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[](作为方法的返回类型。