Last week I've installed the Visual Studio 2015 Enterprise edition (further named: VS2015). I want to perform some test before switching to the newer version. For example backwards compatibility of the project files. I'm ignoring currently all C# 6.0 features, because not all team members have installed their updates to support C# 6.0.
My problem is, that a solution/project which is built with VS2015 has a different behavior in case of exception throwing to the same solution/project which was built with VS2013 (Premium).
Following I'm going to describe the scenario with the code snippets which are failing when built with VS2015.
The behavior of the project built with VS2015 changed as follows:
The code below is throwing an System.ArgumentException with following message: Static method requires null instance, non-static method requires non-null instance. Parameter name: method
Code sippets
//A delegate to convert string values from an array (e3k.Values) to the property type of the desired object.
Func<TE3K, int, Type, object> stringFromDictionary = (e3k, index, type) =>
{
//handle enums
if (type.IsEnum)
{
if (typeof (TE3K) == typeof (VoucherHeader)) //maybe not so good
return VoucherEnumConverter.ToWebEnum(e3k.Values[index], type, e3k.Values);
return DefaultEnumConverter.ToWebEnum(e3k.Values[index], type);
}
//set default value, false if api sends null
if (type == typeof(Boolean) && e3k.Values[index] == null)
return false;
//fix exception when a value like "0" or "1" is converted to boolean.
if (type == typeof(Boolean) && (e3k.Values[index] == "0" || e3k.Values[index] == "1"))
return Convert.ChangeType(Int32.Parse(e3k.Values[index]), type, CultureInfo.InvariantCulture);
//handle nullables
if (Nullable.GetUnderlyingType(type) != null)
return Convert.ChangeType(e3k.Values[index], Nullable.GetUnderlyingType(type), CultureInfo.InvariantCulture);
return Convert.ChangeType(e3k.Values[index], type, CultureInfo.InvariantCulture);
};
MethodInfo getStrValueFromDict = stringFromDictionary.Method;
Description: The object TE3K is an object from an external .dll which I have to convert into an object I can work with. This object of type TE3Khas an array with its values obviously they're all Strings. The parameter intprovides the index for the array (e3k.Values[i]) The parameter Typeis the PropertyTypewhich the string value must be converted into.
//get mapper, sets the index needed in `e3k.Values[index]` for each property of `TWeb`
Dictionary<PropertyInfo, int> mapper = Converter.GetMapper<TE3K, TWeb>();
foreach (var property in mapper)
{
Expression propertyValue = default(Expression);
if (property.Key.PropertyType == typeof(DateTime)) //not relevant for this case
{
propertyValue = Expression.Call(getDateValueFromDict, r, Expression.Constant(property.Value));
}
else if (property.Key.PropertyType == typeof(DateTime?)) //not relevant in this case
{
propertyValue = Expression.Call(getDateValueFromDictSave, r, Expression.Constant(property.Value));
}
else
{
//exception is thrown on this line but only when project is compiled in VS2015
propertyValue = Expression.Call(getStrValueFromDict, r, Expression.Constant(property.Value), Expression.Constant(property.Key.PropertyType));
}
UnaryExpression boxedValue = Expression.Convert(propertyValue, property.Key.PropertyType);
bindings.Add(Expression.Bind(property.Key, boxedValue));
FieldList.Add(property.Value);
}
I now what causes this exception under normal conditions. It's thrown when you make a call to a non static method inside the delegate which is passed into the first parameter of Expression.Call(_delegate, args, ...) or if one of the arguments is a non constant value. (Correct me if I'm wrong here, that is how I understand this.)
Summary
Obviously I'm pretty confused by this behavior. The exception mentioned earlier only occurs when the project is built with VS2015. When built with VS2013the code runs as expected. Are there differences in how visual studio builds and optimizes code between those two versions?
What I've tried
- Compiling on Release/Debug both don't change the behavior.
- Changing C# version does also change nothing.
Feel free to explain extensively if you know a cause. If you need information please ask, I provide them if available.