// Copyright (c) AlphaSierraPapa for the SharpDevelop Team // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; using System.Linq; using System.Threading; #if CS100 using System.Threading.Tasks; #endif namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.DelegateConstruction { public static class DelegateConstruction { private class InstanceTests { public struct SomeData { public string Value; } private int x; public Action CaptureOfThis() { return delegate { CaptureOfThis(); }; } public Action CaptureOfThisAndParameter(int a) { return delegate { CaptureOfThisAndParameter(a); }; } public Action CaptureOfThisAndParameterInForEach(int a) { foreach (int item in Enumerable.Empty()) { if (item > 0) { return delegate { CaptureOfThisAndParameter(item + a); }; } } return null; } public Action CaptureOfThisAndParameterInForEachWithItemCopy(int a) { foreach (int item in Enumerable.Empty()) { int copyOfItem = item; if (item > 0) { return delegate { CaptureOfThisAndParameter(item + a + copyOfItem); }; } } return null; } public void LambdaInForLoop() { for (int i = 0; i < 100000; i++) { Bar(() => Foo()); } } public int Foo() { return 0; } public void Bar(Func f) { } private void Bug955() { new Thread((ThreadStart)delegate { }); } public void Bug951(int amount) { DoAction(delegate { if (amount < 0) { amount = 0; } DoAction(delegate { NoOp(amount); }); }); } public void Bug951b() { int amount = Foo(); DoAction(delegate { if (amount < 0) { amount = 0; } DoAction(delegate { NoOp(amount); }); }); } public void Bug951c(SomeData data) { DoAction(delegate { DoAction(delegate { DoSomething(data.Value); }); }); } public Func Issue2143() { return (int x) => this.x; } public Action Bug971_DelegateWithoutParameterList() { return delegate { }; } private void DoAction(Action action) { } private void NoOp(int a) { } private void DoSomething(string text) { } } public interface IM3 { void M3(); } public class BaseClass : IM3 { protected virtual void M1() { } protected virtual void M2() { } public virtual void M3() { } public static void StaticMethod() { } } public class SubClass : BaseClass { protected override void M2() { } public new void M3() { } public void Test() { Noop("M1.base", base.M1); Noop("M1", M1); Noop("M2.base", base.M2); Noop("M2", M2); Noop("M3.base", base.M3); Noop("M3.base_virt", ((BaseClass)this).M3); Noop("M3.base_interface", ((IM3)this).M3); #if CS70 Noop("M3", this.M3); Noop("M3", M3); #if CS80 static void M3() #else void M3() #endif { } #else Noop("M3", M3); #endif } public void Test2() { Noop("M3.new", new BaseClass().M3); Noop("M3.new", new SubClass().M3); } private void Noop(string name, Action _) { } } public class GenericTest { public Func GetFunc(Func f) { TCaptured captured = f(default(TNonCaptured)); return delegate { Console.WriteLine(captured.GetType().FullName); return captured; }; } public Func GetFunc(Func f) { TCaptured captured = f(); return delegate (TNonCaptured a, TNonCapturedMP d) { Console.WriteLine(a.GetHashCode()); Console.WriteLine(captured.GetType().FullName); return captured; }; } } private delegate void GenericDelegate(); public delegate void RefRecursiveDelegate(ref RefRecursiveDelegate d); public static Func test0 = (string a, string b) => string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b); public static Func test1 = (string a, string b) => string.IsNullOrEmpty(a) || !string.IsNullOrEmpty(b); public static Func test2 = (string a, string b) => !string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b); public static Func test3 = (string a, string b) => !string.IsNullOrEmpty(a) || !string.IsNullOrEmpty(b); public static Func test4 = (string a, string b) => string.IsNullOrEmpty(a) && string.IsNullOrEmpty(b); public static Func test5 = (string a, string b) => string.IsNullOrEmpty(a) && !string.IsNullOrEmpty(b); public static Func test6 = (string a, string b) => !string.IsNullOrEmpty(a) && string.IsNullOrEmpty(b); public static Func test7 = (string a, string b) => !string.IsNullOrEmpty(a) && !string.IsNullOrEmpty(b); public static void Test(this string a) { } public static Predicate And(this Predicate filter1, Predicate filter2) { if (filter1 == null) { return filter2; } if (filter2 == null) { return filter1; } return (T m) => filter1(m) && filter2(m); } public static Action ExtensionMethodUnbound() { return Test; } public static Action ExtensionMethodBound() { return "abc".Test; } public static Action ExtensionMethodBoundOnNull() { return ((string)null).Test; } public static Predicate NoExtensionMethodOnLambda() { return And((int x) => x >= 0, (int x) => x <= 100); } public static object StaticMethod() { return new Func(ExtensionMethodBound); } public static object InstanceMethod() { return new Func("hello".ToUpper); } public static object InstanceMethodOnNull() { return new Func(((string)null).ToUpper); } public static List> AnonymousMethodStoreWithinLoop() { List> list = new List>(); for (int i = 0; i < 10; i++) { int counter; list.Add(delegate (int x) { counter = x; }); } return list; } public static List> AnonymousMethodStoreOutsideLoop() { List> list = new List>(); int counter; for (int i = 0; i < 10; i++) { list.Add(delegate (int x) { counter = x; }); } return list; } public static Action StaticAnonymousMethodNoClosure() { return delegate { Console.WriteLine(); }; } public static void NameConflict() { // i is captured variable, // j is parameter in anonymous method // l is local in anonymous method, // k is local in main method // Ensure that the decompiler doesn't introduce name conflicts List> list = new List>(); for (int k = 0; k < 10; k++) { int i; for (i = 0; i < 10; i++) { list.Add(delegate (int j) { for (int l = 0; l < i; l += j) { Console.WriteLine(); } }); } } } public static void NameConflict2(int j) { List> list = new List>(); for (int k = 0; k < 10; k++) { list.Add(delegate (int i) { Console.WriteLine(i); }); } } public static Action NameConflict3(int i) { return delegate (int j) { for (int k = 0; k < j; k++) { Console.WriteLine(k); } }; } public static Func> CurriedAddition(int a) { return (int b) => (int c) => a + b + c; } public static Func>> CurriedAddition2(int a) { return (int b) => (int c) => (int d) => a + b + c + d; } public static Func CapturedTypeParameter1(TNonCaptured a, Func f) { TCaptured captured = f(a); return delegate { Console.WriteLine(captured.GetType().FullName); return captured; }; } public static Func CapturedTypeParameter2(TNonCaptured a, Func> f) { List captured = f(a); return delegate { Console.WriteLine(captured.GetType().FullName); return captured.FirstOrDefault(); }; } public static Func Issue1773(short data) { int integerData = data; return () => integerData; } #if !MCS // does not compile with mcs... public static Func Issue1773b(object data) { #if ROSLYN dynamic dynamicData = data; return () => dynamicData.DynamicCall(); #else // This is a bug in the old csc: captured dynamic local variables did not have the [DynamicAttribute] // on the display-class field. return () => ((dynamic)data).DynamicCall(); #endif } public static Func Issue1773c(object data) { #if ROSLYN dynamic dynamicData = data; return () => dynamicData; #else return () => (dynamic)data; #endif } #endif #if CS70 public static Func Issue1773d((int Integer, string String) data) { (int Integer, string RenamedString) valueTuple = data; return () => valueTuple.RenamedString; } #endif public static Func Identity() { return (T _) => _; } private static void Use(Action a) { } private static void Use2(Func, IEnumerable> a) { } private static void Use2(GenericDelegate a) { } private static void Use3(Func> a) { } public static void SimpleDelegateReference() { Use(SimpleDelegateReference); #if !MCS2 Use3(Identity); #endif } public static void DelegateReferenceWithStaticTarget() { Use(NameConflict); Use(BaseClass.StaticMethod); } public static void ExtensionDelegateReference(IEnumerable ints) { Use2(ints.Select); } #if CS70 public static void LocalFunctionDelegateReference() { Use(LocalFunction); Use2(LocalFunction1); #if CS80 static void LocalFunction() #else void LocalFunction() #endif { } #if CS80 static void LocalFunction1() #else void LocalFunction1() #endif { } } #endif #if CS90 public static Func LambdaParameterDiscard() { return (int _, int _, int _) => 0; } #endif #if CS100 public static Func LambdaWithAttribute0() { return [My] () => 0; } public static Func LambdaWithAttribute1() { return [My] (int x) => 0; } public static Func LambdaWithAttributeOnParam() { return ([My] int x) => 0; } public static Func> AsyncLambdaWithAttribute0() { return [My] async () => 0; } public static Action StatementLambdaWithAttribute0() { return [My] () => { }; } public static Action StatementLambdaWithAttribute1() { return [return: My] (int x) => { Console.WriteLine(x); }; } public static Action StatementLambdaWithAttribute2() { return ([My] int x) => { Console.WriteLine(x); }; } #endif public static void CallRecursiveDelegate(ref RefRecursiveDelegate d) { d(ref d); } } public class Issue1867 { private int value; public Func TestLambda(Issue1867 x) { Issue1867 m1; Issue1867 m2; if (x.value > value) { m1 = this; m2 = x; } else { m1 = x; m2 = this; } return () => m1.value + 1 == 4 && m2.value > 5; } } internal class Issue2791 { public void M() { Run(delegate (object o) { try { List list = o as List; Action action = delegate { list.Select((int x) => x * 2); }; #if OPT && ROSLYN Action obj = delegate { #else Action action2 = delegate { #endif list.Select((int x) => x * 2); }; Console.WriteLine(); action(); Console.WriteLine(); #if OPT && ROSLYN obj(); #else action2(); #endif } catch (Exception) { Console.WriteLine("catch"); } finally { Console.WriteLine("finally"); } }, null); } private void Run(ParameterizedThreadStart del, object x) { del(x); } } [AttributeUsage(AttributeTargets.All)] internal class MyAttribute : Attribute { } }