概括
忽略对象不能表示为数组的情况,是否可以定义扩展(静态)方法,例如:
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>
?
3 回答
不幸的是,IEnumerator
它早于泛型,所以它没有类型信息;只是尝试强制执行您尝试完成的通用实现并不那么吸引人IEnumerator GetEnumerator()
。String
自从我完成 C# 以来已经有很长时间了,但我想:
public static TElement ToArray<TSource>(this IEnumerable<TElement> source);
...应该没问题:
public static TElement[] ToArray<TElement>(this IEnumerable<TElement> source);
关于扩展方法要记住的重要一点是它们只是语法糖。他们实际上并没有留下来或被注入到他们正在装饰的类型中。它们在编译时被替换为静态方法调用。您使用扩展方法的里程会有所不同。
你的问题具体是什么?如果您要问是否IEnumerable
在编译时总是知道 an 中元素的类型,那么答案是“不,并不总是知道”。非泛型 IEnumerable 不强制任何元素类型。这就是为什么你可以foreach
在 any 上定义一个循环IEnumerable
:
IEnumerable items = GetItems();
foreach(SomeClass item in items)
{
...
}
但这将抛出一个InvalidCastException
if 的元素之一items
不能转换为 a SomeClass
。
顺便说一句,如果您定义这样的方法:
public static TElement[] MyToArray<TElement>(this IEnumerable<TElement> source);
然后您可以string
在 .NET 2.0+中调用它,因为在 .NET 2.0 和 3.0 以及3.5+ 中string
实现。事实上,内置在 .NET 中的扩展已经可以在您不定义任何内容的情况下使用。IEnumerable<string>
IEnumerable<char>
.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
将是 aList<string>
或 an int[]
, 两种类型,它们几乎没有任何共同点,除了可枚举。
因此,为了让您的ToArray
方法正常工作,您可以引入类型安全和泛型,使用IEnumerable<T>
代替IEnumerable
,或使用对象集合,例如object[]
方法的返回类型。