Bug 51964 - With mcs `GetField()` returns null when attempting to access local variables in the captured context of a System.Linq.Expressions.Expression<TDelegate>
Summary: With mcs `GetField()` returns null when attempting to access local variables ...
Status: VERIFIED FEATURE
Alias: None
Product: Compilers
Classification: Mono
Component: C# ()
Version: 4.8.0 (C9)
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: ---
Assignee: Marek Safar
URL:
Depends on:
Blocks:
 
Reported: 2017-01-30 18:14 UTC by David Greene
Modified: 2017-01-31 19:26 UTC (History)
5 users (show)

Tags:
Is this bug a regression?: No
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
VERIFIED FEATURE

Description David Greene 2017-01-30 18:14:01 UTC
*Bug overview:
In a Xamarin.iOS project a GetField() call is returning NULL during runtime. This occurs when built in Xamarin Studio for Mac, but does give the expected value when built in Visual Studio for Windows using the same Mac as a build host.

*Steps to reproduce:
Run the attached sample project, which is attempting to return an object from a MemberExpression:

*Expected Result:
System.Reflection sample code should behave the same when compiled & ran in both Xamarin Studio and Visual Studio.

*Error upon crash:
System.NullReferenceException - Object reference not set to an instance of an object
ReflectionError > Expressions > PropertyExpressionParcer.cs - Line 111

*Versions:
Xamarin Studio 6.1.5 (Build 0)
Mono 4.6.2
Xamarin.iOS 10.3.1.8
Mac OSX 10.11.6
iPhone Simulator - iOS 10.2
Comment 2 Brendan Zagaeski (Xamarin Team, assistant) 2017-01-30 18:30:36 UTC
## Non-engineering team preliminary review

I will assign this bug to myself temporarily for an initial quick review.
Comment 3 Brendan Zagaeski (Xamarin Team, assistant) 2017-01-30 23:56:21 UTC
## Regression status: not a recent regression

BAD: Mono 4.8.0 (mono-4.8.0-branch/cd26828)
BAD: Mono 4.2.4 (explicit/71b88f3)




## Minimized test case

Build the following program with `mcs Program.cs` and then run it using either Mono on Mac or .NET on Windows.

```
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace Program
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            string myString = "Hello";

            Expression<Func<string>> lambdaExpression = () => myString;
            MemberExpression memberExpression = (MemberExpression)(lambdaExpression.Body);

            object objectReference = ((ConstantExpression)(memberExpression.Expression)).Value;

            var result = objectReference.GetType()
                                        .GetField("myString")
                                        .GetValue(objectReference);
            Console.WriteLine(result);
        }
    }
}
```




## "Bad" results when compiled by `mcs`

> Unhandled Exception:
> System.NullReferenceException: Object reference not set to an instance of an object
>   at ConsoleApp1.MainClass.Main (System.String[] args)

(The results are the same whether running with Mono on Mac or .NET on Windows)




## "Good" results when compiled by `csc` on Windows

The program prints out:
> Hello

(The results are the same whether running with Mono on Mac or .NET on Windows)




## Testing environment info (brief)

Mono 4.8.0 (mono-4.8.0-branch/cd26828)
Mac OS 10.11.6

Microsoft (R) Visual C# Compiler version 12.0.30723.0
Microsoft .NET Framework Version 4.6.01055
Windows 8.1 (64-bit) Version 6.3 (Build 9600)

Both systems are set to US English locale and US Eastern time zone
Comment 4 Marek Safar 2017-01-31 17:23:10 UTC
This is kind of feature. Mono C# compiler uses internal visibility for compiler generated fields in compiler generated types and csc uses public visibility.

You can workaround it by using correct visibility flags. Something like

.GetField("myString", BindingFlags.NonPublic | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)
Comment 5 Brendan Zagaeski (Xamarin Team, assistant) 2017-01-31 19:26:01 UTC
Excellent.  Thanks much!




## Verification status: verified answered for the original test case too

I can verify that the approach from Comment 4 works with the original non-public test case too.  I got the desired behavior (no exception, and the app successfully displayed the login fields) when I changed PropertyExpressionParser.cs line 110 to (for example):

.GetField(mi.Name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)

or:

.GetField(mi.Name, BindingFlags.NonPublic | BindingFlags.Instance)