可以/我应该Linqify这个foreach / if / foreach / if / invoke代码吗?

时间:2011-10-21 19:31:32

标签: c# linq observer-pattern

我认为代码可以是Linq:

    foreach (var key in _dic.Keys) // for each observed key
        if (_changedKeys.Contains(key)) // if it changed
            foreach (var item in _dic[key]) // then for each observer
                if (_webSitePage.Session[key] != null) // , as long as the value is something
                    item(_webSitePage.Session[key]); // call the registered delegate

在周围代码的背景下:

public class WebSiteContext
{
    private WebSitePage _webSitePage;

    internal void SetSessionValue<T>(string key, T value)
    {
        object current = _webSitePage.Session[key];
        if (current != null && current.Equals(value)) return;
        _webSitePage.Session[key] = value;
        _changedKeys.Add(key);
    }

    Dictionary<string, List<Action<object>>> _dic = new Dictionary<string, List<Action<object>>>();

    List<string> _changedKeys = new List<string>();

    internal void WhenSessionValueChanges(string key, Action<object> action)
    {
        if (!_dic.ContainsKey(key)) _dic[key] = new List<Action<object>>(); // create on demand
        _dic[key].Add(action);
    }

    internal void PageLoadComplete()
    {
        foreach (var key in _dic.Keys) // for each observed key
            if (_changedKeys.Contains(key)) // if it changed
                foreach (var item in _dic[key]) // then for each observer
                    if (_webSitePage.Session[key] != null) // , as long as the value is something
                        item(_webSitePage.Session[key]); // call the registered delegate

    }
}

public class WebSitePage : System.Web.UI.Page
{
    public WebSitePage()
    {
        this.WebSiteContext = new WebSiteContext(this);
    }

    public WebSiteContext WebSiteContext { get; set; }

    protected override void OnLoadComplete(EventArgs e)
    {
        base.OnLoadComplete(e);
        this.WebSiteContext.PageLoadComplete();
    }
}

4 个答案:

答案 0 :(得分:3)

可以更改为LINQ,但由于你因为副作用而调用item(...),我认为在这里使用LINQ是不合适的,foreach循环更好

但你可以这样写:

 foreach (var key in _dic.Keys.Where(key => _changedKeys.Contains(key))
 {
     foreach (var item in _dic[key])
     {
         var value = _webSitePage.Session[key];
         if (value != null)
         {
             item(value);
         }
     }
 }

答案 1 :(得分:3)

var keys = from key in _dic.Keys
           where _changedKeys.Contains(key) && _webSitePage.Session[key] != null
           from item in _dic[key]
           select item;

foreach (var key in keys)
    item(_webSitePage.Session[key]);

编辑:

以上是非常错误的。道歉。我打算使用查询理解来回答这个问题。这是一次尝试:

var tuples = from key in _dic.Keys
       where _changedKeys.Contains(key) && _webSitePage.Session[key] != null
       from item in _dic[key]
       select new { key, item };

foreach (var t in tuples)
    t.item(_webSitePage.Session[t.key]);

答案 2 :(得分:2)

var keys = _dic.Keys.Where(key => _changedKeys.Contains(key) && 
                                  (_webSitePage.Session[key] != null));
foreach (var key in keys)
  foreach (var item in _dic[key])
    item(_webSitePage.Session[key]);

(第二个测试不需要在内部foreach循环中,除非item修改_webSitePage.Session)

答案 3 :(得分:2)

这缩短了一点。请注意,我移动了_webSitePage检查,因为它不依赖于item的值:

foreach (var kvp in _dic.Where(kvp => !_changedKeys.Contains(kvp.Key) && _webSitePage.Session[kvp.Key] != null))
    foreach (var item in kvp.Values) // then for each observer
        item(_webSitePage.Session[key]); // call the registered delegate