假设我有以下代码:
public static Dictionary<string, ViewModelBase> LoadDictionary()
{
Dictionary<string, ViewModelBase> tempDictionary = new Dictionary<string, ViewModelBase>();
tempDictionary.Add("LoginView", new LoginViewModel());
tempDictionary.Add("SignUpView", new SignUpViewModel());
tempDictionary.Add("ContactListView", new ContactListViewModel());
return tempDictionary;
}
我指的是这一行:
Dictionary<string, ViewModelBase> tempDictionary = new Dictionary<string, ViewModelBase>();
编译器是否首先创建一个构造函数(无参数ctor),然后才添加我的KeyValuePairs?
如果是这样,我的参数ctor将如何(LoadDictionary)?
与这篇文章相关的最重要的问题是:
当我添加 KeyValuePairs 时,是否还实例化值还是等待调用然后实例化?
我的意思是:
new LoginViewModel()
new SignUpViewModel()
new ContactListViewModel()
修改
我只想知道是否
tempDictionary.Add("LoginView", new LoginViewModel());
即使我没有在程序的任何其他部分调用“LoginView”键,也会执行并调用LoginViewModel构造函数。
答案 0 :(得分:1)
注意当您初始化词典时,它将调用视图模型的构造者,如果您希望在访问词典时发生,则可以创建类型{{1的词典并调用一个函数,该函数将返回一个新的ViewModel <string, Func<ViewModel>>
有几种方法可以在c#
中初始化字典您可以使用您正在使用的语法创建字典,然后使用add初始化值。
() => {new ViewModel();}
您可以使用初始化程序创建它,C#5和旧方法将是这样的:
public static Dictionary<string, ViewModelBase> LoadDictionary()
{
Dictionary<string, ViewModelBase> tempDictionary = new Dictionary<string, ViewModelBase>();
tempDictionary.Add("LoginView", new LoginViewModel());
tempDictionary.Add("SignUpView", new SignUpViewModel());
tempDictionary.Add("ContactListView", new ContactListViewModel());
return tempDictionary;
}
注意这是有风险的,因为您可以使用相同的键初始化字典,这将导致错误
这种方式在引擎下调用Add方法更有趣的是你可以重载Add方法来修改你向字典中添加东西的方式,这意味着如果你为Add创建一个重载,那就是(int,ViewModelBase)并且你说你在内部调用了int.ToString(),你也可以在初始化器中使用int。
在C#6.0及更高版本中,有一种初始化字典的新方法,如下所示:
public static Dictionary<string, ViewModelBase> LoadDictionary()
{
return new Dictionary<string, ViewModelBase>() {
{"LoginView", new LoginViewModel()},
{"SignUpView", new SignUpViewModel()},
{"ContactListView", new ContactListViewModel()}
};
}
使用这种方式的好处是,如果您向字典添加具有相同值的条目,它将覆盖旧值并且不会导致错误,您可以在其上找到更多信息here
答案 1 :(得分:0)
编译器是否首先创建一个构造函数(无参数ctor),然后才添加我的KeyValuePairs?
编译器不必创建任何东西。 Dictionary<>
有一个无参数构造函数,您在此处调用:
new Dictionary<string, ViewModelBase>();
您只是调用构造函数,不传递任何参数,并返回Dictionary<string, ViewModelBase>
的实例。
当我添加我的KeyValuePairs时,值是否也被实例化了?
它们是实例化的,因为你要实例化它们:
new LoginViewModel()
与任何其他构造函数一样,这将创建该类的新实例。
请注意,您显示的代码中没有任何代码与类初始值设定项有任何关系。集合类型的初始化程序(如Dictionary<>
)可能如下所示:
Dictionary<string, ViewModelBase> tempDictionary = new Dictionary<string, ViewModelBase>() {
{"LoginView", new LoginViewModel()},
{"SignUpView", new SignUpViewModel()},
{"ContactListView", new ContactListViewModel()}
}
编译的基本上与你所拥有的相同:
Dictionary<string, ViewModelBase> tempDictionary = new Dictionary<string, ViewModelBase>();
tempDictionary.Add("LoginView", new LoginViewModel());
tempDictionary.Add("SignUpView", new SignUpViewModel());
tempDictionary.Add("ContactListView", new ContactListViewModel());
答案 2 :(得分:0)
是的, tempDictionary.Add(&#34; LoginView&#34;,新的LoginViewModel()); 表达式将创建 LoginViewModel 类的新实例,即使您从未尝试访问 tempDictionary 字典对象的 LoginView 键。
答案 3 :(得分:0)
取消你的评论:
@Jonesopolis我只想知道这段代码:
tempDictionary.Add("LoginView", new LoginViewModel());
即使我没有在程序的任何其他部分调用“LoginView”键,也会执行并调用LoginViewModel构造函数。
此代码与:
相同var vm = new LoginViewModel();
tempDictionary.Add("LoginView, vm);
首先执行构造对象(new LoginViewModel()
)的表达式,然后将结果值传递到字典上的Add
方法。所以,是的,你的对象在被传递到字典之前被构造。
你可以编写一个非常简单的程序来自己测试一下。
答案 4 :(得分:0)
我只想知道这段代码:
即使我没有调用&#34; LoginView&#34;也会执行tempDictionary.Add("LoginView", new LoginViewModel());
并调用LoginViewModel构造函数。键入我的程序的任何其他部分。
是的,然后在代码中调用构造函数。如果你想延迟加载它们,你也可以尝试Lazy<T>
类。
var deferredConstructionDict = new Dictionary<string, Lazy<ViewModelBase>>();
deferredConstructionDict.Add("LoginView", new Lazy<ViewModelBase>(() => new LoginViewModel()));
deferredConstructionDict.Add("SignUpView", new Lazy<ViewModelBase>(() => new SignUpViewModel()));
deferredConstructionDict.Add("ContactListView", new Lazy<ViewModelBase>(() => new ContactListViewModel()));
然后通过访问“字典”值的Value
属性来获取模型。
var modelKey = "LoginView";
var myModelFromKey = deferredConstructionDict[modelKey].Value;
原始邮件:
我认为你的问题存在一个根本性的误解,而其他答案并没有解决这个问题。
当我们将一个类作为值初始化时,
Dictionary
如何工作?
我相信你的意思是&#34;在&#34;是Dictionary<string, ViewModelBase>
类型包含类型ViewModelBase
作为第二种泛型类型。 Dictionary<T,U>
类型是泛型类型,在C#中有特殊规则。当C#调用T
的构造函数时,它不会调用U
或Dictionary<T, U>
类型的构造函数,它只会理解有关T
和{{{}}的类型信息{1}}以便运行时知道如何在以后引用时处理存储在字典中的对象。
基本上泛型类型(在你的情况下我指的是U
和string
)是运行时的占位符,C#处理它们的方式是当使用泛型时,在创建泛型类型的实例时,运行时应该能够弄清楚如何处理它们无论使用什么类型。这意味着,即使这样做有意义,ViewModelBase
构造函数也无法调用Dictionary<T,U>
,因为并非所有类型都有构造函数! (例如new ViewModelBase()
)。在C#中,a type is simply some information it knows about an object它在编译和运行时使用它来确定如何处理它。
编译器是否首先创建一个构造函数(无参数ctor),然后才添加我的KeyValuePairs?
不。你编写构造函数,然后调用构造函数。 C#仅在极少数情况下隐式调用构造函数(例如,使用反射)。