The .NET Compiler Platform ("Roslyn") provides open-source C# and Visual Basic compilers with rich code analysis APIs.
JoeRobich on jorobich
Install .NET 6 runtime in corre⦠(compare)
JoeRobich on main-vs-deps
JoeRobich on main-to-main-vs-deps
JoeRobich on main-vs-deps-to-main
dotnet-bot on release
foreach
binds. There's nothing special about the GetEnumerator
method. Just C# recognizes certain patterns when lowering foreach
and VB a different set.
[StandardModule]
public sealed class Tools
{
[IteratorStateMachine(typeof(VB$StateMachine_0_GetEnumerator))]
public static IEnumerable GetEnumerator(this (int, int, int) range)
{
VB$StateMachine_0_GetEnumerator vB$StateMachine_0_GetEnumerator = new VB$StateMachine_0_GetEnumerator(-2);
vB$StateMachine_0_GetEnumerator.$P_range = range;
return vB$StateMachine_0_GetEnumerator;
}
}
@VBAndCs I don't understand what you're saying by "Seems that vb for each was able to consume C# getEnemurator b4 it was added to C#"
Try it on yout machine. The getenumerator extension method works in vb when it is written in C# but doesn't work when it is written in VB! For Each
in vb doesn what foreach in c# does in this matter, but seems the difference is in the generated state machine in both languages, or the way that Yield is implemented in both. Maybe it is a different attribute sued or a missing one. Seems something that can be fixed in vb to have the same functionality as c#.
(int, int, int)
, but you're calling it on (int, int)
just above. Those are different types
IEnumerable
and IEnumerator
.
using System;
using System.Collections;
using System.Runtime.CompilerServices;
foreach (int i in 20..10)
Console.WriteLine(i);
foreach (int i in (10, -10))
Console.WriteLine(i);
foreach (int i in (-10, 10, 3))
Console.WriteLine(i);
public static class Extensions
{
public static IEnumerator GetEnumerator(this System.Range range)
{
int start = range.Start.Value;
int end = range.End.Value;
if (end > start)
for (int i = start; i <= end; i++)
yield return i;
else
for (int i = start; i >= end; i--)
yield return i;
}
public static IEnumerator GetEnumerator(this System.ValueTuple<int, int> range)
{
int start = range.Item1;
int end = range.Item2;
if (end > start)
for (int i = start; i <= end; i++)
yield return i;
else
for (int i = start; i >= end; i--)
yield return i;
}
public static IEnumerator GetEnumerator(this System.ValueTuple<int, int, int> range)
{
int start = range.Item1;
int end = range.Item2;
int step = range.Item3;
if (step > 0)
for (int i = start; i <= end; i+=step)
yield return i;
else
for (int i = start; i >= end; i += step)
yield return i;
}
}
Thanks :)
Yeah I understand. Although a large portion of System.Reflection is to do with statically available info (obviously I don't expect roslyn to be able to give me runtime values if there isn't a program running, so there's no representation of CreateInstance, SetValue, GetValue etc.).
For example PropertyInfo in reflection, and IPropertySymbol in Roslyn
This is the stuff I want to hear about :D. I just want to know if these kinds of relationships are documented somewhere - and is it a value that the roslyn team hold or is any symmetry between the APIs incidental?