Click here to Skip to main content
15,884,472 members
Articles / Programming Languages / C#

Resolving Symbolic References in a CodeDOM (Part 7)

Rate me:
Please Sign up or sign in to vote.
4.75/5 (6 votes)
2 Dec 2012CDDL12 min read 19.4K   509   14  
Resolving symbolic references in a CodeDOM.
// The Nova Project by Ken Beckett.
// Copyright (C) 2007-2012 Inevitable Software, all rights reserved.

// This file contains test code for the Nova.CodeDOM library - it's not designed to be
// executed, only parsed and resolved.

#pragma warning disable  // disable warnings for this file
#undef JUST_TESTING      // undefine symbol
#define UNDOCUMENTED     // define symbol

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;

using Nova.CodeDOM;

using Win = System.Windows;              // namespace alias
using App = System.Windows.Application;  // type alias
using Attribute = System.Attribute;

[assembly: System.Reflection.AssemblyInformationalVersion("0.9")]  // global attribute

namespace Test.Full
{
    using System.Runtime.InteropServices;

    /// <summary>
    /// This is a custom attribute.
    /// </summary>
    [AttributeUsage(AttributeTargets.All)]
    class CustomAttribute : Attribute
    {
        public string Message { get { return null; } set { } }
        public int Value { get { return 0; } set { } }
    }

    // This is a top-level enum declaration
    [Flags]
    public enum TestEnum : byte
    {
        Zero,
#if true
        One = 1,  // EOL comment
#endif
#if true
        // Regular comment
        [Description("two")]
        Two,  // EOL comment
#else
        Too,
#endif
        Four = 4
    }

    /// <summary>
    /// This is a class.
    /// </summary>
    [Custom(Message = "test", Value = 3)]  // class attribute
#if true
    public class TestClass
#else
    class TestClass
#endif
        : ArrayList, IDisposable
    {
        // ENUMS

        // This is a nested enum declaration
        enum E1 { One = 1, Two = 2 }

        enum SingleEnum { LonelyValue }

        // CONSTANTS & FIELDS

        public const int MaxItems = 100;
        [Obsolete("don't use")]  // field attribute
        private string _test;
        private static TestClass _instance;
        private double[,] _2darray;
        private int _a, _b;
        private int _c = 0, _d;
        private const int E = MaxItems;
        private TestEnum _testEnum = TestEnum.Four;

        // CONSTRUCTORS & DESTRUCTORS

        // Static constructor
        static TestClass()
        {
            _instance = new TestClass();
            _instance.Add(null);  // base method call
        }

        /// <summary>
        /// Doc comment with missing language element.
        /// </summary>
        //private int field;

        /// <summary>Default constructor</summary>
        /// test
        public TestClass()
            : base(/*infix*/)
        { }

        /// <summary>
        /// Constructor w/parameter.
        /// </summary>
        /// <param name="test">Test parameter.</param>
        public TestClass(string test)
            : this()
        { }

        public TestClass(int test)  // EOL comment on ConstructorDecl
            // Comment on ConstructorInitializer
            : this("test")  // EOL comment on ConstructorInitializer
        { }

        // Destructor
        ~TestClass()
        { }

        public void Dispose()
        { }

        // PROPERTIES

        /// <summary>
        /// Test property.
        /// </summary>
        /// <value>This is a test value.</value>
        [Custom]  // property attribute
        public string Test
        {
            get { return /*inline*/ _test; }  // getter
            [Custom]
            protected set { _test = value; /* EOL comment */ }  // setter
        }

        // INDEXERS

        /// <summary>
        /// This is an indexer.
        /// </summary>
        /// <param name="p1">First parameter <c>p1</c>.</param>
        /// <param name="p2">Second parameter <paramref name="p2"/>.</param>
        /// <returns>Double result.</returns>
        [Custom]  // indexer attribute
        public double this[int p1, int p2]
        {
            get { return _2darray[p1, p2]; }
            [Custom]
            private set { _2darray[p1, p2] = value; }
        }

        // DELEGATES

        delegate void VoidNoParms();
        public delegate void VoidString(string msg);
        public delegate void VoidTwoParms(double p1, double p2);
        public delegate string StringTwoParms(ref string p1, out double p2);
        private delegate int GenericIntParamsT<T>(params T[] p1) where T : struct;

        private VoidNoParms _del1 = new VoidNoParms(Console.WriteLine);
        private VoidTwoParms _del2 = _instance.MethodVoid2;
        private StringTwoParms _del3 = _instance.MethodString;
        private GenericIntParamsT<int> _del4 = _instance.MethodInt;
        private VoidNoParms _adel1 = delegate { int i = 2; };
        private GenericIntParamsT<int> _adel2 = delegate(int[] ai)  // EOL comment
                                                    {
                                                        return ai.Length;
                                                    };

        public static VoidString WriteLine = new VoidString(Console.WriteLine);

        private static void MethodWithDelegateParameter(string s, VoidNoParms del)
        {
            del();
        }
        private static void MethodWithDelegateParameter(string s, VoidTwoParms del)
        {
            del(1.0, 2.0);
        }
        private static string MethodWithDelegateParameter3(string s, GenericIntParamsT<int> del)
        {
            return (s + del(1, 2));
        }
        private static string MethodWithDelegateParameter4(string s, Func<IEnumerable<double>, string> del)
        {
            return null;
        }
        public void TestDelegates()
        {
            MethodWithDelegateParameter("1a", delegate() { Console.WriteLine(); });
            MethodWithDelegateParameter("1b", Console.WriteLine);
            MethodWithDelegateParameter("1c", Generic<int>);

            MethodWithDelegateParameter("2a", delegate(double a, double b) { a = b; });

            MethodWithDelegateParameter3("3a", delegate { return 1; });
            MethodWithDelegateParameter3("3b", delegate(int[] ai) { return ai.Length; });

            MethodWithDelegateParameter4("4a", string.Concat<double>);

            Action<double, double> dela = delegate(double s1, double s2) { string.Concat(s1, s2); };
            MethodWithDelegateParameter("1a", new VoidTwoParms(dela));

            Func<int[], int> func1b = MethodInt;
        }
        public void Generic<T>()
        { }

        // EVENTS

        event VoidNoParms _event1 = null, _event2 = MethodVoid1;  // field-like events

        // This is an event
        [Custom]  // event attribute
        event VoidNoParms Event2
        {
            [Custom]
            add { _event1 += value; }  // adder
            remove { _event1 -= value; }  // remover
        }

        // OPERATOR OVERLOADING

        public static int operator +(TestClass p) { return 0; }  // unary
        public static int operator +(TestClass left, int right) { return 0; }  // binary
        public static implicit operator string(TestClass p) { return null; }  // implicit conversion
        public static explicit operator double(TestClass p) { return 0; }  // explicit conversion

        public static void OperatorOverloading()
        {
            DateTime dt1 = DateTime.Now;
            TimeSpan diff = DateTime.Now - dt1;
            dt1 += diff;
            dt1.ToString();
            TestClass t = new TestClass();
            int i = t + 5;
            string s = t + " " + t;
            int.Parse(t);
            double d = (double)t;
        }

        // Main Testing Method
        [Conditional("DEBUG"),
            Conditional("TRACE")]  // method attributes
        [Obsolete("Use new method", true)]
        void MethodTest()
        {
            // ----- TYPES -----
            // (using Variables and Literals to test)

            object uo;        // uninitialized
            object o = null;  // null Literal
            bool b1 = true;   // true Literal
            bool b2 = false;  // false Literal
            byte b = 255;
            sbyte sb = -128;
            short s = -32768;
            ushort us = 65535;
            int i = -2147483648;
            uint ui = 4294967295;
            long l = -9223372036854775808l;
            ulong ul = 18446744073709551615L;
            float f1 = 3.4e38f;
            float f2 = -1.5e-45F;
            double d1 = 1.7e308d;
            double d2 = -5.0e-324D;
            double NegativeInfinity = -1.0 / 0.0;
            double PositiveInfinity = 1.0 / 0.0;
            double NaN = 0.0 / 0.0;
            decimal m = 1000000m;
            char c1 = 'a';
            char c2 = '\\';
            string s1 = null;
            string s2 = "\\";
            string s3 = "test";

            // enums
            E1 e1 = (E1)0;
            E1 e2 = E1.Two;
            TestEnum e3 = TestEnum.One | TestEnum.Two | _testEnum;

            // Arrays (simple)
            int[] ia = { 1, 2, 3, i + 2 };
            char[] cha = { ' ', '\'', '"', '\n', '\xffff', (char)(c1 + 2) };
            string[] sa = { "one", "two", s3 + "val" };
            int[] ia2 = new int[2] { 1, 2 };

            // Multi-dimensional Arrays
            double[,] dax2 = { { 1, 2 }, { 3, 4 } };
            double[,] dax2b = new double[2, 2] { { 1, 2 }, { 3, 4 } };

            // Jagged Arrays
            int[][] ijax2 = new int[2][] { new int[] { 1 }, new int[2] { 21, 22 } };
            Test.Full.TestClass[][] ijau = new Test.Full.TestClass[1][];
            int[][,] ijax3 = new int[][,] { new int[,] { { 1 }, { 2 } } };

            // Generic Types
            System.Collections.Generic.List<int> li = new List<int>();
            List<List<int>> lli = new List<List<int>>();

            // Nullable Types
            int? ni = (int?)i;
            System.DateTime? ndt = new System.DateTime?();
            int? ni2 = null;
            Test.Full.TestStruct? ns = null;

            // const
            const int ci = -1;
            const long cl = E + ci;
            const uint cui = 1;
            long csum = cui + ci;
            const string cs1 = " This string has a \n\"linefeed\" in it   ";
            const string cs2 = @"LF esc: \n, double quote: """;
            const string cs3 = "Escapes: \\\'\"\0\a\b\f\n\r\t\v\x0a\x7f\u2425\U0010FFFF";
            const string cs4 = cs2 + cs3;
            string test = cs4 + " " + cl;

            // Use of namespace and type aliases
            Win.Clipboard.Clear();
            App.Current.ToString();
            App app = new App();

            // Hex literals
            b = 0xff;
            sb = 0x7f;
            s = 0x7FFF;
            us = 0xFFFF;
            i = 0x7fffffff;
            ui = 0xffffffff;
            l = 0x7fffffffffffffff;
            ul = 0xffffffffffffffff;
            c1 = (char)0x0041;

            // ----- OPERATORS -----

            // UNARY OPERATORS

            b1 = !b2;     // Not
            i = ~i;       // Complement
            i = +i;       // Positive
            i = -i;       // Negative
            ++i;          // Increment
            --i;          // Decrement
            i++;          // PostIncrement
            i--;          // PostDecrement
            b = (byte)i;  // Cast

            // BINARY OPERATORS

            i = 1;            // Assignment
            i = i + 1;        // Add
            i = i - 1;        // Subtract
            i = i * 1;        // Multiply
            i = i / 1;        // Divide
            i = i % 1;        // Mod
            i = i & 1;        // BitwiseAnd
            i = i | 1;        // BitwiseOr
            i = i ^ 1;        // BitwiseXor
            b1 = (b1 && b2);  // And
            b1 = (b1 || b2);  // Or
            b1 = (i == 1);    // Equal
            b1 = (i != 1);    // NotEqual
            b1 = (i < 1);     // LessThan
            b1 = (i > 1);     // GreaterThan
            b1 = (i <= 1);    // LessThanEqual
            b1 = (i >= 1);    // GreaterThanEqual
            i = (i << 1);     // LeftShift
            i = (i >> 1);     // RightShift
            i += 1;           // AddAssign
            i -= 1;           // SubtractAssign
            i *= 1;           // MultiplyAssign
            i /= 1;           // DivideAssign
            i %= 1;           // ModAssign
            i &= 1;           // BitwiseAndAssign
            i |= 1;           // BitwiseOrAssign
            i ^= 1;           // BitwiseXorAssign
            i <<= 1;          // LeftShiftAssign
            i >>= 1;          // RightShiftAssign
            s1 = (s2 ?? "");  // IfNullThen

            // OTHER OPERATORS

            MethodVoid1();                                     // Call (static)
            _instance.MethodVoid2(1, 2);                       // Call (instance)
            ia[0] = 0;                                         // Index
            o = (b1 ? new Dictionary<int, string>() : null);   // Conditional
            s1 = ((object)o).ToString();                       // Dot
            s1 = (o as string);                                // As
            b1 = (o is int);                                   // Is
            Type t = typeof(Dictionary<,>);                    // TypeOf
            i = sizeof(int);                                   // SizeOf
            i = checked(++i);                                  // Checked
            i = unchecked(++i);                                // Unchecked
            i = new int();                                     // New simple type
            o = new Test.Full.TestClass("test");               // New class
            o = new TestStruct();                              // New struct
            PlatformID p = global::System.PlatformID.Win32NT;  // Lookup

            // This can be used to test loading of private types from referenced assemblies
            //System.Web.DataAccess.SqlConnectionHelper h;

            // ----- EXPRESSIONS -----
            // (see above for Variables & Literals, including const, null, true, false)

            // Compound Variable Declarations
            int mi1, mi2 = 2,  // Number 2
                mi3;  // Third one

            // Parenthesis Usage
            b1 = ((b1 && b2) || (i > 0));  // Nested parens
            i = i - (1 + 2);               // Necessary parens
            i = -(i + 1);                  // Unary operator w/necessary parens
            i = ((i + 1) + 2) + 3;         // Unnecessary parens: ((i + 1) + 2) + 3
            i = (i + 1) + (2 + 3);         // Necessary parens: (i + 1) + (2 + 3)
            i = i + (1 + (2 + 3));         // Necessary parens: i + (1 + (2 + 3))

            // Stand-alone code block
            {  // Infix EOL comment
                // This & Base usage
                o = this;                // this
                this.MethodVoid2(1, 2);  // this scope
                d1 = this[0, 0];         // this indexer
                base.GetType();          // base scope
                o = base[0];             // base indexer
            }

            // Multiple statements on the same line
            s3 = s1; s1 = s2; s2 = s3;  // Swap s1 and s2

            // ----- STATEMENTS -----

            // IF

            // empty statement
            if (i == 1)
                ;  // empty

            // single statement
            if (i == 1)
                i = 2;

            // single statement, same line
            if (i == 2) i = 1;  // single line 'if'

            // block
            if (i == 1) {  // K&R style
                i = 2;
                b1 = true;
            }

            // IF / ELSE

            // empty statement
            if (i == 1)
                ;
            else
                ;

            // single statement
            if (i == 1)
                i = 2;
            else
                i = 1;

            // block
            if (i == 1)
            {
                i = 2;
                b1 = true;
            }
            else
            {
                i = 1;
                b1 = true;
            }

            // IF / ELSE CHAINING

            // WITHOUT else-if chaining
            if (i == 1)
                ;
            // else comment
            else
            {
                // if comment
                if (i == 2)
                {
                    i = 1;
                    b1 = true;
                }
                else  // else EOL comment
                {
                    if (i == 3)  // if EOL comment
                        i = 2;
                    else
                        i = 0;
                }
            }

            // WITH else-if chaining
            if (i == 1)
                ;
            // else-if comment
            else if (i == 2)
            {
                i = 1;
                b1 = true;
            }
            else if (i == 3)  // else-if EOL comment
                i = 2;
            else
                i = 0;

            // SWITCH / CASE / DEFAULT

            // empty switch
            switch (i)
            {
            }

            // single case
            switch (i)
            {
                case 1:
                    b1 = true;
                    break;
            }

            // multiple case, default
            switch (i)
            {
                case 1:  // empty case fall-through
                case 2:
                    // Comment inside brace-less block
                    b1 = true;
                    break;
                // This case has braces for scope
                case 3:
                // Comment outside block after header
                {
                    int a = i;
                    if (a == 1)
                        break;
                    b2 = true;
                    break;
                }
                // This is the default case
                default:
                    b1 = b2 = false;
                    break;
            }

            // GOTO

        Label1:  // first label
        Label2:  // another label
            switch (i)
            {
                case 1:
                    goto Label1;  // goto label
                case 2:
                    goto case (int)(1L * 2);  // goto case
                case 3:
                    goto default;  // goto default
                default:
                    break;
            }

            // WHILE

            // null body
            while (i < 100);

            // empty statement
            while (i < 100)
                ;

            // single statement
            while (i < 100)
                ++i;

            // block
            while (i < 100)
            {
                ++i;
                continue;
            }

            // do infinite loop
            while (true)
            {
                ++i;
                if (i > 100) break;
            }

            // DO / WHILE

            // empty statement
            do
                ;
            while (i < 100);

            // single statement
            do
                ++i;
            while (i < 100);

            // block
            do
            {
                ++i;
                b1 = true;
            }
            while (i < 100);

            // FOR

            // null body
            for (i = 0; i < 100; /*infix*/);

            // empty statement
            for (i = 0; i < 100; ++i)
                ;

            // single statement
            for (int i1 = 0, i2 = 0; i1 < 100; ++i1, --i2)
                i += i1;

            // block
            for (i = 0, l = 0; i < 100; ++i, --l)
            {
                l += i;
                b1 = true;
            }

            // do infinite loop
            for ( ; ; )
                break;

            // FOREACH

            // empty statement
            foreach (int v in ia)
                ;

            // single statement
            foreach (int v in ia)
                i += v;

            // block
            foreach (int v in ia)
            {
                i += v;
                b1 = true;
            }

            // ----- EXCEPTIONS -----

            try  // try
            {
                ++i;
            }
            catch (OverflowException)  // catch w/o variable
            {
                throw;  // re-throw
            }
            catch (StackOverflowException ex)  // catch w/variable
            {
                throw ex;  // new throw
            }
            catch  // catch all exceptions
            { }
            finally  // finally
            {
                b2 = true;
            }

            using (_instance)  // expression
            {
            }
            using (Test.Full.TestClass obj = new TestClass())  // local variable
            {
            }
            using (TestClass obj1 = new TestClass(), obj2 = new TestClass())  // multiple variables
            {
            }
            using (TestClass obj1 = new TestClass())  // multiple nested usings
            using (TestClass obj2 = new TestClass())  // (should display at the same indent level,
            using (TestClass obj3 = new TestClass())  //  and only have braces on the inner-most block)
            {
            }

            // ----- LOCK -----

            // empty statement
            lock (o)
                ;

            // single statement
            lock (o)
                ++i;

            // block
            lock (o)
            {
                ++i;
                b1 = true;
            }

            // ----- METHODS -----

            i = MethodInt(1);
            if (MethodString(/* inline, */ ref s3, out d1) == null)
                i = MethodGeneric<int, object>(o);
            ia = MethodGeneric2(i);
            MethodUIntULong(1u + 1, 1ul - 1);
            MethodUIntULong(ui + 1, ul - 1);

            decimal.Round(b1 ? ci : 100m);
            string.Format("{0} {1}", 1, int.MaxValue);
            string.Format("{0} {1} {2} {3}", 1, int.MaxValue, 2d, 3f);
            string.Format("");
            li.Add(1);

            _del1();
            s1 = _del3(ref s2, out d1);
            i = _del4(1);
            _del1 += MethodVoid1;

            // ----- PROPERTIES -----

            s1 = Test;
            Test = s1;

            // ----- INDEXERS -----

            d1 = _instance[0, 0];
            _instance[0, 0] = d1;

            // ----- EVENTS -----

            Event2 += MethodVoid1;

            // ----- COMMENTS -----

            // This is an independent comment that is split...
            //
            // across 3 lines.

            // This comment is associated with the statement below
            // This is a separate comment associated with the statement below, and
            // it spans two lines.
            i = 1;  // This EOL comment is associated with the statement on the left

            b1 = ((b1 && b2) /* embedded comment */ || !(i > 0));  // EOL comment

            if ((s != null)  // EOL on !=
                && (this.Capacity > 0)  // EOL on '&&' #1
                && System.Console.CursorVisible  // EOL on '&&' #2
                // Postfix comment
                )
            {
                b1 = ((b1  // EOL on b1
                    && ((long)System.Console.BufferWidth  // EOL on cast
                        > 0)  // EOL on '>'
                        // Postfix comment on '>'
                    )  // EOL on '&&'
                    ||  // EOL on ||
                    !(i < 0  // EOL on '0'
                        )  // EOL on '!'
                    );
                object[] objs = new object[]
                                    {
                                        this.Capacity,              // 1st
                                        (long)Console.BufferWidth,  // 2nd
                                        (b1 && b2) || (i == 0),     // 3rd
                                        s                           // 4th
                                    };
                int i1 = 1,  // 1
                    i2 = 2,  // 2
                    i3 = (int)Console.BufferWidth;  // 3
            }

            // There is a triple blank line after this comment...



            /* Block comment Line 1
             *    Line 2 */
            /* Block comment Line 1
             *    Line 2
             *    Line 3
             */

            // TODO: This is a 'to-do' comment

            // ----- COMPILER DIRECTIVES -----

            #region /* COMPILER DIRECTIVES */

            // See top of file for #define/#undef examples, since they can only legally appear there

#if (TEST1 && TEST2 && TEST3) || !TEST4 || ((TEST5 == true) && (TEST6 != false))  // comment

#if TEST1  // conditional compilation
            // This 'code' will not be compiled:
            It's not actually code, but that doesn't matter.
#elif TEST2  // elif
            This text won't be compiled.
#else  // else

#warning Warning message!
//#error Error message!

            #line 999 "C:\path\test.cs"  // comment
            #line hidden  // comment
            #line default  // comment

#endif  // endif

#endif

            string[] cds =
                {  // EOL comment
                    // Regular comment
                    "one",
#if false
                    "too",
#else
                    // Regular comment
                    "two"  // EOL comment
#endif
#if false
                    "three"
#endif
                };

#pragma warning disable  // comment
#pragma warning restore  // comment
#pragma warning disable 78, 219, 1691  // comment
#pragma warning restore 78, 219, 1691  // comment
#pragma warning disable

#pragma checksum "test.cs" "{00000000-0000-0000-0000-000000000000}" "01234567"  // comment

            #endregion /* COMPILER DIRECTIVES */
        }

        // ----- OTHER METHODS -----

        static void MethodVoid1(/*infix*/)  // No parameters, empty body, static
        { }

        new void MethodVoid2(double p1, double p2)  // Two parameters
        {
            return;  // Return with no value
        }

        void MethodUIntULong(uint p1, ulong p2)
        { }

        /// <summary>
        /// Test method with <b>one</b> parameter.
        /// The <paramref name="pa"/> parameter is an <i>optional</i> list of <c>int</c>.
        /// Use standard XML escapes to embed chars such as: &lt; &amp; &gt;
        /// <para>2nd paragraph</para>
        /// <see cref="string.IndexOf"/>
        /// <seealso cref="MethodString(ref string, out double)"/>
        /// Generics can be referenced like <see cref="List{T}"/>.
        /// </summary>
        /// <param name="pa"></param>
        /// <returns>The result.</returns>
        /// <exception cref="System.Exception">Thrown when...</exception>
        /// <permission cref="System.Security.PermissionSet">Everyone can access this method.</permission>
        /// <remarks>
        /// This is the remarks section.
        /// <see cref="System.Threading.Monitor.Enter(object, ref bool)"/>
        /// Here is a list:
        /// <list type="bullet">
        ///     <listheader>
        ///         <term>Header Term</term>
        ///         <description>Header Description</description>
        ///     </listheader>
        ///     <item>
        ///         <term>Term 1</term>
        ///         <description>Description 1.</description>
        ///     </item>
        ///     <item>
        ///         <term>Term 2</term>
        ///         <description>Description 2.</description>
        ///     </item>
        /// </list>
        /// </remarks>
        /// <example>This example shows how to call the <see cref="MethodInt"/> method.
        /// <code>
        /// int result = MethodInt(10);
        /// List{int} list = new List&lt;int&gt;();
        /// bool b = (result &amp; 0x80) &lt;= 3;
        /// object o = list[0];
        /// int i = MethodGeneric{int, object}(o);
        /// string s = "&lt;&amp;&gt;";
        /// if (b)
        /// {
        ///     if (result &gt; 0)
        ///         Console.WriteLine("");
        /// }
        /// </code>
        /// </example>
        int MethodInt(/*inline*/ params int[] pa)  // One parameter
        {
            return (pa[0] * -1);  // Return a value
        }

        string MethodString(ref string p1,
            out double p2)  // Two parameters
        {
            p2 = 0;
            return p1;
        }

        /// <summary>
        /// Generic method.
        /// </summary>
        /// <typeparam name="T">Type parameter T.</typeparam>
        /// <typeparam name="U">Type parameter U.</typeparam>
        /// <param name="u">Parameter u.</param>
        /// <returns>Result T.</returns>
        T MethodGeneric<T, U>(U u)  // EOL comment on GenericMethodDecl
            where T : U  // EOL comment on 1st constraint
            where U : class  // EOL comment on 2nd constraint
        {
            return ((u == null) ? default(T) : (T)u);
        }

        new T[] MethodGeneric2<T>(T obj)
        {
            return new T[1];
        }

        public IEnumerator<int> GetEnumerator()  // Iterator
        {
            yield return 1;
            yield return 2;
            yield break;
        }

        [DllImport("kernel32", SetLastError = true, ExactSpelling = true)]
        static extern bool RemoveDirectory(string name);  // extern - no body

        void AMethod([In, Out] ref double x)  // parameter attributes
        { }

        // This is a nested, generic interface
        interface InnerInterface<T>
        {
            void Method();
            string Property { get; set; }
            T this[T i] { get; }
            event VoidNoParms Event;
        }

        /// <summary>
        /// This is a nested, generic class.
        /// </summary>
        /// <typeparam name="T">Type parameter T.</typeparam>
        /// <typeparam name="U">Type parameter U.</typeparam>
        class InnerClass<T, U>  // EOL comment on ClassDecl
            // Comment on base-type list
            : InnerInterface<T>  // EOL comment on base type/interface
            // Comment on constraints
            where T : struct where U : TestClass, new()  // EOL comment on constraints
        {
            protected T t;
            public U u;
            public InnerInterface<T> p;
            private static readonly InnerClass<int, TestClass> _instance;
            private Inner2<long> _inner2;

            // Static constructor
            static InnerClass()
            {
                _instance = new InnerClass<int, TestClass>();
                Type t1 = ((InnerInterface<T>)_instance).GetType();
                Type t2 = ((IList)new List<T>()).GetType();
                _instance._inner2 = new InnerClass<int, TestClass>.Inner2<long>();
                string s = _instance._inner2.Inner2Generic(1, TestClass._instance, 2L, TestClass._instance);
            }

            // Explicit interface implementations
            void InnerInterface<T>.Method() { }
            string InnerInterface<T>.Property { get { return ""; } set { } }
            T InnerInterface<T>.this[T i] { get { return default(T); } }
            event VoidNoParms InnerInterface<T>.Event { add { } remove { } }

            /// <summary>
            /// Nested, generic type, with generic method referencing parent type parameters.
            /// </summary>
            /// <typeparam name="V">Type parameter V.</typeparam>
            private class Inner2<V> where V : IComparable
            {
                /// <summary>
                /// Inner2Generic test method.
                /// This method has generic parameter <typeparamref name="W"/>.
                /// </summary>
                /// <typeparam name="W">Type parameter W.</typeparam>
                /// <param name="t">Parameter t.</param>
                /// <param name="u">Parameter u.</param>
                /// <param name="v">Parameter v.</param>
                /// <param name="w">Parameter w.</param>
                /// <returns>String result.</returns>
                public string Inner2Generic<W>(T t, U u, V v, W w) where W : U
                {
                    return (t.ToString() + u + v + w);
                }
            }
        }

        /// <summary>
        /// This is a nested struct, generic on <typeparamref name="T"/>.
        /// </summary>
        /// <typeparam name="T">Type parameter.</typeparam>
        public struct InnerStruct<T>
        {
        }

        class InnerDerived : InnerClass<DateTime, TestClass>
        {
            void Method()
            {
                int v = t.Hour;
            }
        }

        class TestCollection<TItem> : List<TItem>
        {
        }
        void CollectionMethod(List<TestClass> list)
        { }
        void TestGenericCollection()
        {
            TestCollection<TestClass> collection = new TestCollection<TestClass>();
            CollectionMethod(collection);
        }

        public class TestBase<T>
        {
            private T t = default(T);
            public T Property { get { return t; } }
        }
        public class InnerTest : TestBase<TestClass>
        {
            public void Test()
            {
                string s1 = Property.Test;
            }
        }
    }

    // This is a top-level interface
    public interface ITestInterface : IComparable
    {
    }

    /// <summary>
    /// This is a top-level struct
    /// </summary>
    public struct TestStruct
    {
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)


Written By
Software Developer (Senior)
United States United States
I've been writing software since the late 70's, currently focusing mainly on C#.NET. I also like to travel around the world, and I own a Chocolate Factory (sadly, none of my employees are oompa loompas).

Comments and Discussions