/// <summary>
        /// Attempt to evaluate the specified source code.
        /// The provided source code will be compiled (unless cached) and then executed in <see cref="ScriptDomain"/> specified in the constructor.
        /// Any valid C# method body syntax is accepted. You may not define user types or methods in the provided source. Type declarations are allowed.
        /// </summary>
        /// <typeparam name="T">The generic type that the evaluated code should return</typeparam>
        /// <param name="sourceCode">The string source code to execute</param>
        /// <returns>A <see cref="Variable"/> representing the return value of the evaluated code. If the evaluated code does not return a value then the result will be a <see cref="Variable"/> representing 'default(T)'. If the code failed to run then the return value will be null</returns>
        public Variable <T> Eval <T>(string sourceCode)
        {
            ScriptProxy proxy = null;

            // Check whether this source is cached
            bool isCached = evalCache.ContainsKey(sourceCode);

            // Check if we have a cached version of this source code
            if (isCached == true)
            {
                // Get the cached type
                proxy = evalCache[sourceCode];
            }
            else
            {
                // Get the full C# source code
                string source = BuildSourceAroundTemplate(sourceCode);

#if UNITY_EDITOR && !UNITY_WEBPLAYER
                // Check if we should output the generated source
                if (outputGeneratedSourceIfDebug == true)
                {
                    System.IO.File.WriteAllText("DynamicCSharp_Eval_GeneratedSource.cs", source);
                }
#endif

                // Try to compile the code
                ScriptType type = domain.CompileAndLoadScriptSource(source);

                // Looks like we failed to compile or find a cached type
                if (type == null)
                {
                    return(null);
                }

                // Create an instance
                proxy = type.CreateInstance();

                // Check for error
                if (proxy == null)
                {
                    return(null);
                }
            }

            // Check if we need to cache the type
            if (isCached == false)
            {
                // Make a cache entry
                evalCache.Add(sourceCode, proxy);
            }

            // Bind the delegates to the proxy
            BindProxyDelegates(proxy);

            // Bind the values to the proxy
            BindProxyVars(proxy);

            // Bind our return value
            object returnResult = new object();

            proxy.Fields[returnObject] = returnResult;

            // Call the method
            object result = proxy.SafeCall(entryMethod);

            // Read the value back into evaluator memory space
            UnbindProxyVars(proxy);

            // Check if we returned a value
            if (returnResult == result)
            {
                return(new Variable <T>(returnObject, default(T)));
            }

            // Create a default error value that we can use if we fail to get the correct type
            T resolvedReturn = default(T);

            try
            {
                // Try to cast to type
                resolvedReturn = (T)result;
            }
            catch (InvalidCastException) { }

            // We successfully ran the code
            return(new Variable <T>(returnObject, resolvedReturn));
        }