// 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.Linq.Expressions; using System.Xml; public class ExpressionTrees { class GenericClass { public static X StaticField; public X InstanceField; public static X StaticProperty { get; set; } public X InstanceProperty { get; set; } public static bool GenericMethod() { return false; } } int field; static object ToCode(object x, Expression> expr) { return expr; } static object ToCode(object x, Expression> expr) { return expr; } static object X() { return null; } public void Parameter(bool a) { ToCode(X(), () => a); } public void LocalVariable() { bool a = true; ToCode(X(), () => a); } public void LambdaParameter() { ToCode(X(), (bool a) => a); } public void AddOperator(int x) { ToCode(X(), () => 1 + x + 2); } public void AnonymousClasses() { ToCode(X(), () => new { X = 3, A = "a" }); } public void ArrayIndex() { ToCode(X(), () => new[] { 3, 4, 5 }[0 + (int)(DateTime.Now.Ticks % 3)]); } public void ArrayLengthAndDoubles() { ToCode(X(), () => new[] { 1.0, 2.01, 3.5 }.Concat(new[] { 1.0, 2.0 }).ToArray().Length); } public void AsOperator() { ToCode(X(), () => new object() as string); } public void ComplexGenericName() { ToCode(X(), () => ((Func)(x => x > 0))(0)); } public void DefaultValue() { ToCode(X(), () => new TimeSpan(1, 2, 3) == default(TimeSpan)); } public void EnumConstant() { ToCode(X(), () => new object().Equals(MidpointRounding.ToEven)); } public void IndexerAccess() { var dict = Enumerable.Range(1, 20).ToDictionary(n => n.ToString()); ToCode(X(), () => dict["3"] == 3); } public void IsOperator() { ToCode(X(), () => new object() is string); } public void ListInitializer() { ToCode(X(), () => new Dictionary { { 1, 1 }, { 2, 2 }, { 3, 4 } }.Count == 3); } public void ListInitializer2() { ToCode(X(), () => new List(50) { 1, 2, 3 }.Count == 3); } public void ListInitializer3() { ToCode(X(), () => new List { 1, 2, 3 }.Count == 3); } public void LiteralCharAndProperty() { ToCode(X(), () => new string(' ', 3).Length == 1); } public void CharNoCast() { ToCode(X(), () => "abc"[1] == 'b'); } public void StringsImplicitCast() { int i = 1; string x = "X"; ToCode(X(), () => (("a\n\\b" ?? x) + x).Length == 2 ? false : true && (1m + -i > 0 || false)); } public void NotImplicitCast() { byte z = 42; ToCode(X(), () => ~z == 0); } public void MembersBuiltin() { ToCode(X(), () => 1.23m.ToString()); ToCode(X(), () => AttributeTargets.All.HasFlag((Enum)AttributeTargets.Assembly)); ToCode(X(), () => "abc".Length == 3); ToCode(X(), () => 'a'.CompareTo('b') < 0); } public void MembersDefault() { ToCode(X(), () => default(DateTime).Ticks == 0); ToCode(X(), () => default(int[]).Length == 0); ToCode(X(), () => default(Type).IsLayoutSequential); ToCode(X(), () => default(List).Count); ToCode(X(), () => default(int[]).Clone() == null); ToCode(X(), () => default(Type).IsInstanceOfType(new object())); ToCode(X(), () => default(List).AsReadOnly()); } public void DoAssert() { field = 37; ToCode(X(), () => field != C()); ToCode(X(), () => !ReferenceEquals(this, new ExpressionTrees())); ToCode(X(), () => MyEquals(this) && !MyEquals(default(ExpressionTrees))); } int C() { return field + 5; } bool MyEquals(ExpressionTrees other) { return other != null && field == other.field; } public void MethodGroupAsExtensionMethod() { ToCode(X(), () => (Func)new[] { 2000, 2004, 2008, 2012 }.Any); } public void MethodGroupConstant() { ToCode(X(), () => Array.TrueForAll(new[] { 2000, 2004, 2008, 2012 }, DateTime.IsLeapYear)); HashSet set = new HashSet(); ToCode(X(), () => new[] { 2000, 2004, 2008, 2012 }.All(set.Add)); Func, bool> sink = f => f(null, null); ToCode(X(), () => sink(int.Equals)); } public void MultipleCasts() { ToCode(X(), () => 1 == (int)(object)1); } public void MultipleDots() { ToCode(X(), () => 3.ToString().ToString().Length > 0); } public void NestedLambda() { Func, int> call = f => f(); //no params ToCode(X(), () => call(() => 42)); //one param ToCode(X(), () => new[] { 37, 42 }.Select(x => x * 2)); //two params ToCode(X(), () => new[] { 37, 42 }.Select((x, i) => x * 2)); } public void CurriedLambda() { ToCode>>(X(), a => b => c => a + b + c); } bool Fizz(Func a) { return a(42); } bool Buzz(Func a) { return a(42); } bool Fizz(Func a) { return a("42"); } public void NestedLambda2() { ToCode(X(), () => Fizz(x => x == "a")); ToCode(X(), () => Fizz(x => x == 37)); ToCode(X(), () => Fizz((int x) => true)); ToCode(X(), () => Buzz(x => true)); } public void NewArrayAndExtensionMethod() { ToCode(X(), () => new[] { 1.0, 2.01, 3.5 }.SequenceEqual(new[] { 1.0, 2.01, 3.5 })); } public void NewMultiDimArray() { ToCode(X(), () => new int[3, 4].Length == 1); } public void NewObject() { ToCode(X(), () => new object() != new object()); } public void NotOperator() { bool x = true; int y = 3; byte z = 42; ToCode(X(), () => ~(int)z == 0); ToCode(X(), () => ~y == 0); ToCode(X(), () => !x); } public void ObjectInitializers() { XmlReaderSettings s = new XmlReaderSettings { CloseInput = false, CheckCharacters = false }; ToCode(X(), () => new XmlReaderSettings { CloseInput = s.CloseInput, CheckCharacters = s.CheckCharacters }.Equals(s)); } public void Quoted() { ToCode(X(), () => (Expression>)((n, s) => s + n.ToString()) != null); } public void Quoted2() { ToCode(X(), () => ToCode(X(), () => true).Equals(null)); } public void QuotedWithAnonymous() { ToCode(X(), () => new[] { new { X = "a", Y = "b" } }.Select(o => o.X + o.Y).Single()); } public void StaticCall() { ToCode(X(), () => Equals(3, 0)); } public void ThisCall() { ToCode(X(), () => !Equals(3)); } public void ThisExplicit() { ToCode(X(), () => object.Equals(this, 3)); } public void TypedConstant() { ToCode(X(), () => new[] { typeof(int), typeof(string) }); } public void StaticCallImplicitCast() { ToCode(X(), () => Equals(3, 0)); } public void StaticMembers() { ToCode(X(), () => (DateTime.Now > DateTime.Now + TimeSpan.FromMilliseconds(10.001)).ToString() == "False"); } public void Strings() { int i = 1; string x = "X"; ToCode(X(), () => (("a\n\\b" ?? x) + x).Length == 2 ? false : true && (1m + (decimal)-i > 0m || false)); } public void StringAccessor() { ToCode(X(), () => (int)"abc"[1] == 98); } public void GenericClassInstance() { ToCode(X(), () => new GenericClass().InstanceField + new GenericClass().InstanceProperty); } public void GenericClassStatic() { ToCode(X(), () => GenericClass.StaticField + GenericClass.StaticProperty); } public void InvokeGenericMethod() { ToCode(X(), () => GenericClass.GenericMethod()); } }