2016-02-25 123 views
0

我已經在winforms中創建了自定義按鈕,其中我已經添加屬性與自定義類的列表:List<Zasoby>和只有當該列表中已滿足特定項目的項目添加到此列表的方法標準(lambda .where表達式)。 類Zasob是可序列化的。 而在設計師,我首先添加到Zasob列表中該按鈕是這樣的:ArgumentOutOfRangeException儘管邊界檢查

bt01008xxx.Zasoby.Add(new Zasob { Lokalizacja = new Lokalizacja("01", "008", "000") }); 

..

public class ZasobSzczegolowoButton: Button, IAddZasoby 
{ 

    private List<Zasob> _zasoby = new List<Zasob>(); //{ new Zasob { Lokalizacja = new Lokalizacja("01", "001", "000") } }; 


    [EditorBrowsable(EditorBrowsableState.Always)] 
    [Browsable(true)] 
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] 
    [Bindable(true)] 
    public List<Zasob> Zasoby 
    { 
     get { return _zasoby; } 
     set 
     { 
      _zasoby = value; 
      if (_zasoby.Any()) BackColor = _zasoby.Sum(x => x.Ilosc) > 0 ? Color.Coral : Color.White; 
     } 
    } 

    public void AddZasoby(List<Zasob> zasoby) 
    { 
     var buton = Name; 
     if (_zasoby != null && _zasoby.Count != 0) 
     { 
      var szukaneZasoby = 
       zasoby?.Where(
        x => 
         x.Lokalizacja.ObszarKod == _zasoby[0].Lokalizacja.ObszarKod && 
         x.Lokalizacja.Segment1 == _zasoby[0].Lokalizacja.Segment1); 
      if (szukaneZasoby == null) return; 

      Zasoby.Clear(); 
      Zasoby.AddRange(szukaneZasoby); 
     } 
    } 
} 

...

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate,Inherited = false)] 
[ComVisible(true)] 
public class Zasob : Attribute 
{ 
    public Towar Towar { get; set; } 
    public Magazyn Magazyn { get; set; } 
    public Lokalizacja Lokalizacja { get; set; } 
    public decimal Ilosc { get; set; } 
} 

現在,每當我嘗試使用方法AddZasoby我得到System.ArgumentOutOfRangeException。我檢查列表中的空值和計數項目,並在調試模式下,它應該退出方法,但仍然以某種方式結束在錯誤的方法的主體。 (請看下面的截圖) 任何想法我做錯了什麼?

1

+0

我不明白你的代碼....你爲什麼繼承自屬性和使用它像poco類? – Viru

+0

,因爲我從設計器接收到可序列化的錯誤,所以我認爲我應該爲該類添加SerializableAttribute。它幫助了我收到的錯誤。 – mdziadowiec

回答

2

您正確檢查列表計數,但與代碼Zasoby.Clear();你清楚的成員變量_zasoby再次那些元素。

不要讓它欺騙自己:你定義你清除列表Where() -clause 但它會在事後執行!這是lambda表達式的訣竅,您在Where() -lambda中編寫的謂詞只會在評估後立即執行。

此功能稱爲延期執行,請參見the first example here

爲了解決這個問題,你可以強制拉姆達被調用ToArray()ToList()立即執行之前,你清楚你的列表,如:

public void AddZasoby(List<Zasob> zasoby) 
    { 
     var buton = Name; 
     if (_zasoby != null && _zasoby.Count != 0) 
     { 
      var szukaneZasoby = 
       zasoby?.Where(
        x => 
         x.Lokalizacja.ObszarKod == _zasoby[0].Lokalizacja.ObszarKod && 
         x.Lokalizacja.Segment1 == _zasoby[0].Lokalizacja.Segment1 
        ).ToList(); // *** NOTE ME HERE *** 

      if (szukaneZasoby == null) return; 

      Zasoby.Clear(); 
      Zasoby.AddRange(szukaneZasoby); 
     } 
    } 

這應該做的伎倆。

+0

確實有幫助。謝謝@Waescher。我tottaly忘記延期執行。我盯着這段代碼太久了,開始覺得我瘋了,因爲沒有在if子句中忽略簡單的bool邏輯。 – mdziadowiec