The .NET Compiler Platform ("Roslyn") provides open-source C# and Visual Basic compilers with rich code analysis APIs.
CyrusNajmabadi on main
Simplify TypeKind condition Apply suggestions from code rev… Update src/Features/Core/Portab… and 1 more (compare)
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?
IsNullableTypeOrTypeParameter (https://sourceroslyn.io/#Microsoft.CodeAnalysis.CSharp/Symbols/TypeSymbolExtensions.cs,113) checks if a constraint type is a nullable type.
But how is this ever possible since structs can't be constraints? Is it only if the constraint is defined in a different language?
lower
a code block to a classic simple C#/VB code and show it in a readoly code window. Pattern matching expressions are in top of things that may need explanation
. I may go far and say every new concept since Roslyn can be considered hard and nee to be explained. This can be a useful educational feature, and ease the pain for new team members that joins a large project. VS offers to simplify expressions which in most cases means shorten them into a complex modern syntax! We may need an action on the opposite direction. This seems a lot of work, but it can make use of the Roslyn code itself if it lowers these statements.