Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# NET 3.5/4.0中的空条件运算符模拟,与2012/2013相比?_C#_Linq_Nullable_Null Conditional Operator - Fatal编程技术网

C# NET 3.5/4.0中的空条件运算符模拟,与2012/2013相比?

C# NET 3.5/4.0中的空条件运算符模拟,与2012/2013相比?,c#,linq,nullable,null-conditional-operator,C#,Linq,Nullable,Null Conditional Operator,在我的代码中,我必须访问调用多个属性getter的值: IFoo1 a = objA.Prop1.Value; IFoo2 b = objB.Prop2.Prop3.Value; IFoo3 c = objC.Prop4.Prop5.Prop6.Value; 每个属性都可以为null。因此,要访问每个值,我必须使用嵌套if块: IFoo2 b = null; if(objB.Prop2!=null) { if(objB.Prop2.Prop3!=null) {

在我的代码中,我必须访问调用多个属性getter的值:

IFoo1 a = objA.Prop1.Value;
IFoo2 b = objB.Prop2.Prop3.Value;
IFoo3 c = objC.Prop4.Prop5.Prop6.Value;
每个属性都可以为null。因此,要访问每个值,我必须使用嵌套if块:

IFoo2 b = null;

if(objB.Prop2!=null)
{
    if(objB.Prop2.Prop3!=null)
    {
         b = objB.Prop2.Prop3.Value;
    }
}
如何改进此代码以减少if块的数量?我是否可以使用任何lambda表达式、LINQ、IExpression等以某种方式将其替换为:

ifoo2b=GetVal(objB.Prop2.Prop3.Value)

所有的PropX都是不同类型的,我有数百个这样的属性。 我必须使用.NET3.5或至少.NET4.0。我不能使用任何更高版本

重要编辑:


我还必须使用Visual Studio 2012和2013。我无法确定VS 2015的目标。

.NET 4.6现在有一个?。解决这个问题的运算符

这允许你这样写

IFoo3 c=objC?.Prop4?.Prop5?.Prop6?.Value


您可以通过创建一个helper函数来解决这个问题,但是代码的清晰性和简单性无法达到这一点。如果可能的话,升级以获得该功能。

您可能能做的最好的方法是使用化合物
If
条件,如

IFoo2 b = null;

if(objB.Prop2 != null && objB.Prop2.Prop3 != null)
{ 
  b = objB.Prop2.Prop3.Value;
}
(或)使用
三元运算符

IFoo2 b = (objB.Prop2 != null && objB.Prop2.Prop3 != null) ? objB.Prop2.Prop3.Value : null;

这样就可以了,但速度很快而且很脏。一些明显的缺陷:

  • 对于表达式a.b.c-我们调用'a',然后调用'a.b',然后调用'a.b.c',每次都检查null。我们应该存储上一次调用的返回,并修改成员表达式以对结果进行操作。只有当成员访问非常昂贵时才是真正的问题,否则它相当于
    如果(a!=null&&a.b!=null&&a.b.c!=null)返回a.b.c.d这是一种相当常见的模式
  • 它只适用于成员表达式
  • 不幸的是,您需要C#6来使用空条件运算符(
    ?。

    但是,可以使用以下扩展方法对其进行模拟:

    static class Extensions
    {
        public static TReturn NCR<T, TReturn>(this T instance, Func<T, TReturn> getter)
            where T : class
            where TReturn : class
        {
            if (instance != null)
                return getter(instance);
            return null;
        }
    
        public static TReturn NCR<T, TReturn>(this T? instance, Func<T, TReturn> getter)
            where T : struct
            where TReturn : class
        {
            if (instance != null)
                return getter(instance.Value);
            return null;
        }
    
        public static TReturn? NCV<T, TReturn>(this T instance, Func<T, TReturn> getter)
            where T : class
            where TReturn : struct
        {
            if (instance != null)
                return getter(instance);
            return null;
        }
    
        public static TReturn? NCV<T, TReturn>(this T? instance, Func<T, TReturn> getter)
        where T : struct
        where TReturn : struct
        {
            if (instance != null)
                return getter(instance.Value);
            return null;
        }
    }
    
    (如果要获取的属性返回值类型,请使用NCV而不是NCR)


    它仍然太冗长,但至少更容易看到代码在做什么。

    请查看此处的学生类:,我有同样的问题。您使用的是哪个版本的VS?如果是VS2015,您可以使用C#6 null条件运算符,即使是针对.NET 3.5或4.0,我也必须使用.NET 3.5或.NET 4.0。新运算符与C#编译器绑定,而不是.NET。(它基本上会发出所有通常“手动”执行的错误检查代码。)不管使用哪个.NET版本,只要使用的是C#6编译器,而不是.NET 4.6,它的C#6.0,因为它是一个组件特性nit CLR。有没有可能在VS 2012或至少2013中模拟空条件运算符?您正在运行时编译动态方法,然后使用反射调用它们,而不使用任何缓存。这是一个很好的解决方案,但应该非常谨慎地使用。性能影响将在10000倍或更慢的范围内。
    var tmp = new classA();
    
    var res = GetOrNull(() => tmp.Prop1.Prop2);
    res.Dump(); //Gives null
    
    tmp.Prop1 = new classA.classB();
    tmp.Prop1.Prop2 = new classA.classB.classC();
    res = GetOrNull(() => tmp.Prop1.Prop2);
    res.Dump(); //returns object of type `classC`
    
    static class Extensions
    {
        public static TReturn NCR<T, TReturn>(this T instance, Func<T, TReturn> getter)
            where T : class
            where TReturn : class
        {
            if (instance != null)
                return getter(instance);
            return null;
        }
    
        public static TReturn NCR<T, TReturn>(this T? instance, Func<T, TReturn> getter)
            where T : struct
            where TReturn : class
        {
            if (instance != null)
                return getter(instance.Value);
            return null;
        }
    
        public static TReturn? NCV<T, TReturn>(this T instance, Func<T, TReturn> getter)
            where T : class
            where TReturn : struct
        {
            if (instance != null)
                return getter(instance);
            return null;
        }
    
        public static TReturn? NCV<T, TReturn>(this T? instance, Func<T, TReturn> getter)
        where T : struct
        where TReturn : struct
        {
            if (instance != null)
                return getter(instance.Value);
            return null;
        }
    }
    
    IFoo3 c = objC.NCR(_ => _.Prop4)
                  .NCR(_ => _.Prop5)
                  .NCR(_ => _.Prop6)
                  .NCR(_ => _.Value);