From a62e13a035a38072d45b9a8476565e34fe08520b Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 1 Oct 2017 02:55:40 +0200 Subject: [PATCH] Improve detection of foreach-using in UsingTransform: The C# compiler only expects: - EnumeratorType GetEnumerator(); on the type of the in-expression. - EnumeratorType must implement the following members: * bool MoveNext(); * T Current { get; } --- .../IL/Transforms/UsingTransform.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs index a39916d1b..f74df84dc 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs @@ -97,7 +97,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms // This is a workaround for non-generic foreach. if (type.IsKnownType(KnownTypeCode.IEnumerator)) return true; - return NullableType.GetUnderlyingType(type).GetAllBaseTypes().Any(b => b.IsKnownType(KnownTypeCode.IDisposable)); + if (NullableType.GetUnderlyingType(type).GetAllBaseTypes().Any(b => b.IsKnownType(KnownTypeCode.IDisposable))) + return true; + // General GetEnumerator-pattern? + if (!type.GetMethods(m => m.Name == "GetEnumerator" && m.TypeParameters.Count == 0 && m.Parameters.Count == 0).Any(m => ImplementsForeachPattern(m.ReturnType))) + return false; + return true; + } + + bool ImplementsForeachPattern(IType type) + { + if (!type.GetMethods(m => m.Name == "MoveNext" && m.TypeParameters.Count == 0 && m.Parameters.Count == 0).Any(m => m.ReturnType.IsKnownType(KnownTypeCode.Boolean))) + return false; + if (!type.GetProperties(p => p.Name == "Current" && p.CanGet && !p.IsIndexer).Any()) + return false; + return true; } bool MatchDisposeBlock(BlockContainer container, ILVariable objVar, bool usingNull)