No, it is not possible - since yield
is a contextual keyword being processed by the compiler during the compilation process, you cannot check for it directly (see yield contectual keyword) - you can find here a list of contectual keywords the language C# provides.
Definition
A contextual keyword, such as yield
, is used to provide a specific meaning in the code, but it is not a reserved word in C#. Some contextual keywords, like partial
and where
, have special meanings in two or more contexts.
You can find a similar explanation here, why you can't find it out easily with reflection.
But I think that it should be sufficient to check for IEnumerable
- because this interface guarantees that an Iterator is available (see iterators). Consider the following method:
IEnumerable<int> Iterator()
{
for (int i = 0; i < 10; i++)
{
yield return i;
};
}
One way to check if you can do a iteration is:
if (Iterator() is IEnumerable)
foreach (var item in Iterator())
{
Debug.WriteLine(item.ToString());
}
else
Debug.WriteLine("Cannot iterate!");
Another way is declarative through Generics:
void Iterate<T>(T iterator)
where T: System.Collections.IEnumerable
{
foreach (var item in iterator)
{
Debug.WriteLine(item.ToString());
}
}
You can invoke this via:
Iterate(Iterator());
The difference is, that that via Generics the compiler will check it and give you a compile error before the application runs, while the first example checks it on runtime, i.e. it will compile but fail on runtime.
Of course, you can also iterate through an array, this works perfectly fine (see comment below added by CodeCaster):
var intArray = new int[] {1,2,3};
Iterate(intArray);
You can also check for an enumerator explicitly, i.e.
void Iterate2<T>(T collection)
where T: IEnumerable
{
var enumerator = collection.GetEnumerator();
if (enumerator is IEnumerator)
while (enumerator.MoveNext())
{
var item = enumerator.Current;
Console.WriteLine(item.ToString());
}
}
I've put the examples together as
.NET Fiddle
so you can try it out instantly.