繁体   English   中英

调用谓词将引发NullReferenceException

[英]Invoking a predicate throws NullReferenceException

我具有可以提供值的不同属性,我想返回第一个满足指定条件的属性。

问题是当源之一是class并且为null ,我确实得到了一个不错的Object引用,但未将其设置为对象的实例。

我无法在Func<T,bool>Expression<Func<Media,T>>找到一个属性来检查当前提供程序的无效性。

您知道如何检查功能目标的无效性吗?

public int TempoInteger
{
    get
    {
        double result;
        // In this case, AudioSummary is a class that can be null
        if (TryGetValue(out result, s => s > 0.0d, s => s.TempoBass, s => s.AudioSummary.Tempo))
        {
            return (int)Math.Round(result);
        }
        return -1;
    }
}

private AudioSummary AudioSummary {get; set;}

/// <summary>
/// Tries to get a value from multiple expressions, first expression value that satisfies the predicate will be returned. If no value satisifes the predicate the default value of <typeparamref name="T"/> will be returned.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="result"></param>
/// <param name="predicate"></param>
/// <param name="expressions"></param>
/// <returns></returns>
private bool TryGetValue<T>(out T result, Func<T, bool> predicate, params Expression<Func<Media, T>>[] expressions)
{
    foreach (var expression in expressions)
    {
        Func<Media, T> func = expression.Compile();

        // 'System.NullReferenceException' occurs here when AudioSummary is null
        T t = func(this);

        var b = predicate(t);
        if (b)
        {
            result = t;
            return true;
        }
    }
    result = default(T);
    return false;
}

public sealed class AudioSummary
{

    [JsonProperty("tempo")]
    public double Tempo { get; set; }

    // ...

}

对于您要实现的目标,有几种解决方法。

  1. 将表达式调用包装在try-catch块中

     private bool TryGetValue<T>( out T result, Func<T, bool> predicate, params Expression<Func<Media, T>>[] expressions) { ... T t; try { t = func(this); } catch (NullReferenceException) { t = default(T); } ... } 
  2. 在将表达式传递给TryGetValue()之前验证Null表达式

     public int TempoInteger { get { double result; if (TryGetValue(out result, s => s > 0.0d, s => s.TempoBass, s => s.AudioSummary != null ? s.AudioSummary.Tempo : 0.0d)) { return (int)Math.Round(result); } return -1; } } 
  3. 使用IfNotNull扩展方法,该方法与#2点的功能相同,但效果更好

     public static class IfNotNullExtensionMethod { public static T2 IfNotNull<T1, T2>(this T1 t, Func<T1, T2> fn) where T1: class { return t != null ? fn(t) : default(T2); } } ... public int TempoInteger { get { double result; if (TryGetValue(out result, s => s > 0.0d, s => s.TempoBass, s => s.AudioSummary.IfNotNull(x => x.Tempo))) { return (int)Math.Round(result); } return -1; } } ... 

    对于信用 IfNotNull扩展方法去: 在这里在这里 ,并在这里

  4. 使用Maybe扩展方法: maybe.codeplex.com (免责声明:我尚未测试过这一点,但在#3点积分链接中已提及)

调用之前TryGetValue()检查空物体sAudioSummary因为如果AudioSummary为空,你不能让财产AudioSummary.Tempo

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM