2012-03-07 18 views
7

Podczas pracy z MVVM i Prism znajdę się robić dużo odlewania, jak większość parametry są interfejsyCo Koszt parametrów odlewania

Ex

public void AddCrSubSystemsToPlant(IPlantItem plantItm, CRArticleItem crItm) 
     { 

      OSiteSubSystem itm = (OSiteSubSystem)crItm; 
      itm.PartData.Order = ((OSiteEquipment)plantItm).SubSystems.Count() + 1; 

      ((OSiteEquipment)plantItm).SubSystems.Add(itm); 

     } 

lub

public void DeletePart(IPlantItem plantItem) 
     { 
      IEnumerable<IPlantItem> itmParent = GetParentPartByObjectId(_siteDocument, plantItem); 

      if (plantItem is OSiteEquipment) 
      ((ObservableCollection<OSiteEquipment>)itmParent).Remove((OSiteEquipment)plantItem); 

      if (plantItem is OSiteSubSystem) 
       ((ObservableCollection<OSiteSubSystem>)itmParent).Remove((OSiteSubSystem)plantItem); 

      if (plantItem is OSiteComponent) 
       ((ObservableCollection<OSiteComponent>)itmParent).Remove((OSiteComponent)plantItem); 
     } 

My Pytanie brzmi, jaki jest koszt. Czy te operacje są kosztowne, czy też procesorowe, należy ich unikać.

Jakieś widoki?

+10

Dlaczego trzeba wszystkie te odlewy? Czy interfejsy nie ujawniają wymaganych operacji? Jeśli nie, dlaczego nie? – Oded

+1

Prawdopodobnie możesz sfałszować niektóre przypadki testowe z odlewaniem i bez niego i zmierzyć wydajność. Nie sądzę, by jakakolwiek indywidualna obsada miała duży wpływ na wydajność, ale zależy od tego, jak często to robisz. –

+0

Zobacz tę odpowiedź: http://stackoverflow.com/a/9366456/414076 –

Odpowiedz

7

Myślę, że ważniejsze pytanie brzmi: dlaczego robisz tak dużo castingów?

W pierwszym przykładzie:
Dlaczego jest pierwszy parametr typ IPlantItem Jeśli trzymasz rzucając go OSiteEquipment? To samo można powiedzieć o drugim parametrze.

W drugim przykładzie:
Dlaczego GetParentPArtByObjectId zwraca wartość IEnumerable<IPlantItem>? Jeśli miałby zwrócić wartość ICollection<IPlantItem>, nie musiałbyś przesyłać go pod numer ObservableCollection<T>. ObservableCollection<T> dziedziczy z Collection<T>, która implementuje zarówno ICollection<T>, jak i ICollection. Powinieneś być w stanie usunąć przedmiot z kolekcji, nawet nie znając jego typu.

Teraz kilka porad.
Nie należy wielokrotnie rzucać tego samego obiektu.
nie rób tego:

if (obj is IPlantItem) 
    ((IPlantItem)obj).DoSomething(); 

Czy zamiast tego

IPlantItem plant = obj as IPlantItem; 
if (plant != null) 
    plant.DoSomething(); 

rodzajów Wykorzystanie bazy w miarę możliwości.To powstrzyma cię od rzucania tak bardzo. Jak wcześniej wspomniano, nie należy odlewać do ObserableCollection<T>, aby wywołać metodę na ICollection

Użyj generycznych. Jeśli potrzebujesz logiki specyficznej dla typu, utwórz abstrakcyjną klasę bazową (lub po prostu interfejs, jeśli nie potrzebujesz żadnej logiki współdzielonej) z parametrem generycznym. Następnie wykonaj implementacje tej klasy dla każdej implementacji interfejsu. Metody mogą być również ogólne. Mogę przepisać drugi przykład jako

public void DeletePart<TPlantItem>(TPlantItem plantItem) 
    where TPlantItem : IPlantItem 
{ 
    IEnumerable<TPlantItem> itmParent = GetParentPartByObjectId(_siteDocument, plantItem); 
    ((ObservableCollection<TPlantItem>)itmParent).Remove(plantItem); 
} 
+0

Powodzenia w testowaniu jednostkowym, gdy implementacja wymaga rzeczywistej implementacji, a nie zachowania interfejsu. – weismat

+0

Dlatego zaleciłem zmianę typów parametrów zamiast rzutowania i ogólne abstrakcyjne klasy bazowe/interfejsy z implementacjami specyficznymi dla typu. – cadrell0

+0

Mimo, że dałeś OP, czego potrzebował, myślę, że dawanie mu tego, czego chciał ("Ile kosztuje rzucanie?"), Przynajmniej w skrócie, byłoby dobre. – svick

0

Ten artykuł może rzucić pewne światło na sposób odlewania wpływa na wydajność

http://www.codeproject.com/Articles/8052/Type-casting-impact-over-execution-performance-in

Oto kilka ogólnych wskazówek dotyczących optymalizacji programów opartych na wyników uzyskanych w poprzednich sekcjach:

  • Typowe typy konwersji są zazwyczaj drogie, wyjmij je z pętli i funkcji rekursywnych i użyj tych samych typów liczbowych kiedy jest możliwe .

  • Downcasting to świetny wynalazek, ale kontrole typu mają duży wpływ na wydajność wykonania, sprawdzają typy obiektów poza pętlami i funkcjami rekursywnymi, i używają w nich operatora "as".

  • Upcasting jest tani !, używaj go wszędzie, gdzie potrzebujesz.

  • Twórz lekkie operatory konwersji, aby wykonać niestandardowe odlewy szybciej. Używane narzędzia
+0

Pamiętaj, że artykuł ma prawie 8 lat. –

+0

Odkryłem, że większość tych zasad i wyników pozostaje w posiadaniu, chociaż liczby mogą być nieaktualne. – Ani

1

użytku

 ((System.Collections.IList)itmParent).Remove(plantItem); 

zamiast

 if (plantItem is OSiteEquipment) 
     ((ObservableCollection<OSiteEquipment>)itmParent).Remove((OSiteEquipment)plantItem); 

     if (plantItem is OSiteSubSystem) 
      ((ObservableCollection<OSiteSubSystem>)itmParent).Remove((OSiteSubSystem)plantItem); 

     if (plantItem is OSiteComponent) 
      ((ObservableCollection<OSiteComponent>)itmParent).Remove((OSiteComponent)plantItem);