Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.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# 用 空合并运算符??: int length = customers?.Length ?? 0; // 0 if customers is null_C#_Extension Methods - Fatal编程技术网

C# 用 空合并运算符??: int length = customers?.Length ?? 0; // 0 if customers is null

C# 用 空合并运算符??: int length = customers?.Length ?? 0; // 0 if customers is null,c#,extension-methods,C#,Extension Methods,空条件运算符显示短路行为, 当紧接其后的成员链访问时,元素 只有在原始 接收方不为空: int? first = customers?[0].Orders.Count(); 该示例实质上等同于: int? first = (customers != null) ? customers[0].Orders.Count() : null; 除了只对客户进行一次评估。没有成员 访问、元素访问和调用紧随其后? 除非客户具有非空值,否则将执行 当然,空条件运算符本身也可以链接,例如 如果需要在链中多次

空条件运算符显示短路行为, 当紧接其后的成员链访问时,元素 只有在原始 接收方不为空:

int? first = customers?[0].Orders.Count();
该示例实质上等同于:

int? first = (customers != null) ? customers[0].Orders.Count() : null;
除了只对客户进行一次评估。没有成员 访问、元素访问和调用紧随其后? 除非客户具有非空值,否则将执行

当然,空条件运算符本身也可以链接,例如 如果需要在链中多次检查null:

int? first = customers?[0].Orders?.Count();
请注意,调用(带括号的参数列表)不能 立即跟进?操作员–这将导致太多 句法歧义。因此,调用 只有在不起作用的情况下才授权。但是,您可以通过 委托上的Invoke方法:

if (predicate?.Invoke(e) ?? false) { … }
我们希望这种模式的一个非常常见的用途是 触发事件:

PropertyChanged?.Invoke(this, args);
这是一种简单且线程安全的方法,可以在使用前检查null 触发事件。它是线程安全的原因是 仅对左侧求值一次,并将其保留在临时位置 变数


不过,这会强制实现不变性(至少是冰棒不变性),并且不能很好地处理“default(t)”等问题。此外,它更普遍地假设您确实控制了所讨论的类型(情况并非总是如此);在某些情况下,只有“in-line if”才能起作用,例如在为LINQ to(某些数据库)构建lambda时,“in-line if”指的是?:操作符?对不起,我指的是一个noraml“if”语句,它没有隐藏在单独的方法中。谢谢-删除了括号。我认为SafeSelect会建议一个枚举,但它不是。。。关于取消引用,我不确定。。。最难的部分总是命名:)我必须同意Marc,你的扩展方法不像??代码示例中的运算符。哇!我知道ext.方法基本上是“thiscall”静态方法,但我仍然认为它们在对Null实例调用时会抛出Null引用异常(因为非虚拟实例方法实际上以相同的方式工作)。。。我想这种方式更有意义。谢谢你的评论!这正是我想要的——或者说不是想要的;)API应该遵循“最小惊喜原则”——所以我想使用扩展方法不是一个好主意——我会重新考虑我的设计!查看我的更新-C#6很可能有你想要的:)谢谢,已经在这里绊倒了;)他需要lambdas,因为
something\u other
something
的属性。将属性解引用封装在lambda中允许他延迟评估它,直到他知道这样做是安全的。这样做是错误的方法,因为您将该知识推给了原始方,而原始方应该是黑盒。如果您想要lazy-eval,只需使用lazy-eval类包装您的属性,并将这样的混合传递给方法(在这里合并)。否则你会以coalesce,coalesce\u lazy,等等结束。
Console.WriteLine(
  Coalesce.UntilNull(getSomeFoo(), f => f.Value) ?? "default value");
public class Bar
{
  public Bar Child { get; set; }
  public Foo Foo { get; set; }
}

Bar bar=new Bar { Child=new Bar { Foo=new Foo("value") } };

// prints "value":
Console.WriteLine(
  Coalesce.UntilNull(bar, b => b.Child, b => b.Foo, f => f.Value) ?? "null");

// prints "null":
Console.WriteLine(
  Coalesce.UntilNull(bar, b => b.Foo, f => f.Value) ?? "null");
var street = customer?.PrimaryAddress?.Street;
var street = customer?.PrimaryAddress?.Street ?? "(no address given)";
Console.WriteLine(getSomeFoo()?.Value ?? "default"); 
possiblyNull?.SomeMethod();
f => f.Value
public class Foo
{
  public Foo(string value) { Value=value; }
  public string Value { get; private set; }
  private static Foo nullFoo = new Foo("default value");
  public static Foo NullFoo { get { return nullFoo; } }
}
public class NullFoo : Foo
{
    private NullFoo() : base("default value") { }
    private static NullFoo instance = new NullFoo();
    public static Foo Instance { get { return instance; } }
}
Console.WriteLine((getSomeFoo() ?? NullFoo.Instance).Value);
public static TResult Coalesce<T, TResult>(this T obj, Func<T, TResult> func, TResult defaultValue)
{
    if (obj == null)
        return defaultValue;

    return func(obj);
}

public static TResult Coalesce<T1, T2, TResult>(this T1 obj, Func<T1, T2> func1, Func<T2, TResult> func2, TResult defaultValue)
{
    if (obj == null)
        return defaultValue;

    T2 obj2 = func1(obj);
    if (obj2 == null)
        return defaultValue;

    return func2(obj2);
}

public static TResult Coalesce<T1, T2, T3, TResult>(this T1 obj, Func<T1, T2> func1, Func<T2, T3> func2, Func<T3, TResult> func3, TResult defaultValue)
{
    if (obj == null)
        return defaultValue;

    T2 obj2 = func1(obj);
    if (obj2 == null)
        return defaultValue;

    T3 obj3 = func2(obj2);
    if (obj3 == null)
        return defaultValue;

    return func3(obj3);
}

public static TResult Coalesce<T1, T2, T3, T4, TResult>(this T1 obj, Func<T1, T2> func1, Func<T2, T3> func2, Func<T3, T4> func3, Func<T4, TResult> func4, TResult defaultValue)
{
    if (obj == null)
        return defaultValue;

    T2 obj2 = func1(obj);
    if (obj2 == null)
        return defaultValue;

    T3 obj3 = func2(obj2);
    if (obj3 == null)
        return defaultValue;

    T4 obj4 = func3(obj3);
    if (obj4 == null)
        return defaultValue;

    return func4(obj4);
}
BinaryTreeNode node = LocateNode(someKey);
BinaryTreeNode grandFatherNode = node.Coalesce(n1 => n1.Parent, n2 => n2.Parent, null);
BinaryTreeNode grandFatherNode = node.Parent.Parent; // or null if none
coalesce(something, something_else, "default");
    public static class Coalesce
    {
        public static TResult UntilNull<T, TResult>(T obj, Func<T, TResult> func) where TResult : class
        {
            if (obj != null) return func(obj);
            else return null;
        }

        public static TResult UntilNull<T1, T2, TResult>(T1 obj, Func<T1, T2> func1, Func<T2, TResult> func2) where TResult : class
        {
            if (obj != null) return UntilNull(func1(obj), func2);
            else return null;
        }

        public static TResult UntilNull<T1, T2, T3, TResult>(T1 obj, Func<T1, T2> func1, Func<T2, T3> func2, Func<T3, TResult> func3) where TResult : class
        {
            if (obj != null) return UntilNull(func1(obj), func2, func3);
            else return null;
        }

        public static TResult UntilNull<T1, T2, T3, T4, TResult>(T1 obj, Func<T1, T2> func1, Func<T2, T3> func2, Func<T3, T4> func3, Func<T4, TResult> func4) where TResult : class
        {
            if (obj != null) return UntilNull(func1(obj), func2, func3, func4);
            else return null;
        }

        public static Nullable<TResult> UntilNull<T, TResult>(T obj, Func<T, Nullable<TResult>> func) where TResult : struct
        {
            if (obj != null) return func(obj);
            else return new Nullable<TResult>();
        }

        public static Nullable<TResult> UntilNull<T1, T2, TResult>(T1 obj, Func<T1, T2> func1, Func<T2, Nullable<TResult>> func2) where TResult : struct
        {
            if (obj != null) return UntilNull(func1(obj), func2);
            else return new Nullable<TResult>();
        }

        public static Nullable<TResult> UntilNull<T1, T2, T3, TResult>(T1 obj, Func<T1, T2> func1, Func<T2, T3> func2, Func<T3, Nullable<TResult>> func3) where TResult : struct
        {
            if (obj != null) return UntilNull(func1(obj), func2, func3);
            else return new Nullable<TResult>();
        }

        public static Nullable<TResult> UntilNull<T1, T2, T3, T4, TResult>(T1 obj, Func<T1, T2> func1, Func<T2, T3> func2, Func<T3, T4> func3, Func<T4, Nullable<TResult>> func4) where TResult : struct
        {
            if (obj != null) return UntilNull(func1(obj), func2, func3, func4);
            else return new Nullable<TResult>();
        }
    }
int? length = customers?.Length; // null if customers is null Customer
first = customers?[0];  // null if customers is null
int length = customers?.Length ?? 0; // 0 if customers is null
int? first = customers?[0].Orders.Count();
int? first = (customers != null) ? customers[0].Orders.Count() : null;
int? first = customers?[0].Orders?.Count();
if (predicate?.Invoke(e) ?? false) { … }
PropertyChanged?.Invoke(this, args);