पर कॉल में फ़ील्ड वैरिएबल पर कैप्चर करना क्यों है, मैं हाल ही में लैम्ब्डा अभिव्यक्ति और परिवर्तनीय कैप्चर के साथ एक अजीब चीज से थोड़ा सा था। कोड .NET 4.5 (VS2012) का उपयोग कर एक WPF/MVVM एप्लिकेशन था।मुझे लैम्ब्डा को कन्स्ट्रक्टर
public class MyViewModel : ViewModelBase
{
public MyViewModel(Action menuCallback)
{
MyCommand = new RelayCommand(menuCallback);
}
public MyViewModel(Func<ViewModelBase> viewModelCreator)
// I also tried calling the other constructor, but the result was the same
// : this(() => SetMainContent(viewModelCreator())
{
Action action =() => SetMainContent(viewModelCreator());
MyCommand = new RelayCommand(action);
}
public ICommand MyCommand { get; private set; }
}
: मैं अपने viewmodel के विभिन्न निर्माताओं सेटअप करने के लिए एक RelayCommand
के लिए कॉलबैक उपयोग कर रहा था (यह आदेश तो मेरे विचार में एक मेनू आइटम करने के लिए बाध्य किया जाता था)
संक्षेप में, मैं निम्नलिखित कोड था और उसके बाद का उपयोग करके उपरोक्त के उदाहरण बनाया:
// From some other viewmodel's code:
new MyViewModel(() => new SomeViewModel());
new MyViewModel(() => new SomeOtherViewModel());
ये तो एक WPF मेनू करने के लिए बाध्य कर रहे थे - प्रत्येक मेनू आइटम अपने डेटा संदर्भ के रूप में एक MyViewModel उदाहरण था। अजीब चीज यह थी कि मेनू केवल एक बार काम करता था। चाहे मैंने कोशिश की वस्तुओं में से कोई भी, यह उपयुक्त Func<ViewModelBase>
- लेकिन केवल एक बार कॉल करेगा। अगर मैंने एक और मेनू आइटम या फिर भी वही आइटम चुनने का प्रयास किया, तो यह काम नहीं करता है। किसी भी त्रुटि के बारे में वीएस डीबग आउटपुट में कुछ भी नहीं कहा गया और कोई आउटपुट नहीं मिला।
मैं छोरों में चर कैप्चर के मुद्दे से परिचित हूँ, इसलिए मैं एक अनुमान है कि इस मुद्दे को संबंधित था बनाया तो मेरी वी एम के लिए बदल दिया:
public class MyViewModel : ViewModelBase
{
public MyViewModel(Action buttonCallback)
{
MyCommand = new RelayCommand(buttonCallback);
}
private Func<ViewModelBase> _creator;
public MyViewModel(Func<ViewModelBase> viewModelCreator)
{
// Store the Func<> to a field and use that in the Action lambda
_creator = viewModelCreator;
var action =() => SetMainContent(_creator());
MyCommand = new RelayCommand(action);
}
public ICommand MyCommand { get; private set; }
}
और उसी तरह यह कहा जाता है। अब सबकुछ काम करता है जैसा इसे करना चाहिए।
बस मस्ती के लिए, मैं भी पूरे Func<ViewModelBase>
निर्माता के आसपास MyViewModel
निर्माता की उचित Action
बाहर बनाने के द्वारा काम किया:
// This code also works, even without the _creator field in MyViewModel
new MyViewModel(() => SetMainContent(new SomeViewModel()));
new MyViewModel(() => SetMainContent(new SomeOtherViewModel()));
तो मैं यह काम कर रहा करने के लिए कामयाब रहे, लेकिन मैं अभी भी उत्सुक हूँ क्यों यह इस तरह काम करता है। कंपाइलर कन्स्ट्रक्टर में Func<ViewModelBase>
को सही तरीके से कैप्चर नहीं करता है?
क्या आपने दो दृष्टिकोणों के लिए उत्पन्न आईएल में मतभेदों को देखा है? यह कुछ संकेत दे सकता है। – nicodemus13
यदि 'SetMainContent'' ViewModelBase' वर्ग में है, तो आप इसे अपने अंतिम कोड उदाहरण में लैम्ब्डा में कैसे कॉल कर रहे हैं जो काम करता है? – Pat
SetMainContent मुख्य विंडो के व्यूमोडेल में व्यूमोडेल उदाहरण भेजने के लिए संदेशों (एमवीवीएमएल से) का उपयोग करता है। इसके बाद इसे एक सामग्री प्रॉपर्टी को असाइन किया जाएगा जो यूआई में प्रस्तुत किया जाता है। मैं एक और पूर्ण कोड उदाहरण के साथ आने का प्रयास करूंगा जो इस मुद्दे को प्रदर्शित करता है –