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 TE3K
has an array with its values obviously they're all Strings
. The parameter int
provides the index for the array (e3k.Values[i]
) The parameter Type
is the PropertyType
which 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 VS2013
the 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.