2014-02-14 49 views
0

我有不同的属性,可以提供一个值,我想返回第一个满足指定条件。调用谓词抛出NullReferenceException

问题是,当其中一个来源是class,是null,我得到不设置到对象的实例很好对象引用。

我无法找到属性来检查当前提供程序的无效性,无论是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; } 

    // ... 

} 
+0

我没有看到'AudioSummary'代码,除了评论... – Blorgbeard

+0

我添加代码的属性和类的修剪定义。 – Aybe

回答

4

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

  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()

    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扩展方法,之前的表达式Null内的表达式调用其与点#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扩展方法去:hereherehere

  4. 使用Maybe扩展方法:maybe.codeplex.com(免责声明:我没有测试过这一个,但它在点提到#3学分链接)

+0

3号很棒,谢谢! – Aybe

+0

@Aybe我很高兴它帮助... – IronGeek

1

调用TryGetValue()检查空对象之前和s因为AudioSummary如果AudioSummary为空,你不能让财产AudioSummary.Tempo

相关问题