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
Sub Main(args As String())
For Each i In (1, 10, 2).GetEnumerator()
Console.WriteLine(i)
Next
Imports System.Runtime.CompilerServices
Public Module Tools
<Extension>
Public Iterator Function GetEnumerator(range As ValueTuple(Of Integer, Integer, Integer)) As IEnumerable
Dim start = range.Item1
Dim [end] = range.Item2
Dim [step] = range.Item3
If ([step] > 0) Then
For i = start To [end] Step [step]
Yield i
Next
Else
For i = start To [end] Step [step]
Yield i
Next
End If
End Function
End Module
(1, 10, 2).GetEnumerator()
expression works, but (1, 10, 2)
doesn't!
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#.
One difference is that it's missing the
[Extension]
attribute?
this is the code I get back from ILSpy. I use the Extension attribute in the code as I posted before, and I show you that calling the .GetEnumerator explicitly works only for the one written in VB not 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?