-1

Assuming I have the following code:

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;
}

I refer to this line:

Dictionary<string, ViewModelBase> tempDictionary = new Dictionary<string, ViewModelBase>();

Does the compiler first create a constructor (parameterless ctor) and only then add my KeyValuePairs?

If so, how will my parameter ctor would look like (of the LoadDictionary)?

And the most important question relevant to this post is:

When I add my KeyValuePairs, are the Values also instantiated or do they wait to called and then are instantiated?

I mean to:

new LoginViewModel()
new SignUpViewModel()
new ContactListViewModel()


EDIT:

I Simply want to know if

tempDictionary.Add("LoginView", new LoginViewModel());

would be executed and call the LoginViewModel constructor even if I did not call the "LoginView" key in any other part of my program.

Axel
  • 3,331
  • 11
  • 35
  • 58
monogate
  • 1,419
  • 1
  • 11
  • 16
  • 4
    I honestly don't understand your questions – Jonesopolis Sep 07 '16 at 18:11
  • The list of constructors is [here](https://msdn.microsoft.com/en-us/library/6918612z(v=vs.110).aspx), so the SO answer you linked is saying that it calls the parameterless one to create the object then adds the things to it later, it doesn't use some other constructor. You are not making a dictionary constructor, parameterless or otherwise (you have a method, not a constructor), and don't have to think about making one. As for your other question, yes, the Values are instantiated because it runs that code when the `.Add()` method runs. – Quantic Sep 07 '16 at 18:11
  • 2
    Dictionary already has a constructor. The compiler doesn't create a new one for you. Nowhere are you calling a collection initializer, which is the subject of your first boldface blockquote from the documentation. I think you have some mistaken assumptions about the meaning of a lot of the terminology here, and you're going off on some strange tangent based on your misunderstandings. – 15ee8f99-57ff-4f92-890c-b56153 Sep 07 '16 at 18:12
  • @Jonesopolis I Simply wanna know if this code: tempDictionary.Add("LoginView", new LoginViewModel()); would be executed and call the LoginViewModel constructor even if I did not call the "LoginView" key in any other part of my program. – monogate Sep 07 '16 at 18:12
  • What does "class initializer" mean to you, in plain English? – 15ee8f99-57ff-4f92-890c-b56153 Sep 07 '16 at 18:13
  • @EdPlunkett I've edited my post to be more specific – monogate Sep 07 '16 at 18:14
  • @monogate The answer to that question is that yes, that `LoginViewModel` constructor is called right there. That new instance of `LoginViewModel` is added to your dictionary, whether or not you ever do anything with that dictionary key again. This is not a LINQ-style deferred thing; it's all happening right then and there. – 15ee8f99-57ff-4f92-890c-b56153 Sep 07 '16 at 18:14
  • _I Simply wanna know if this code:..._ Of course it will call `LoginViewConstructor` – Dusan Sep 07 '16 at 18:15
  • 4
    @monogate it feels you are missing some very basic knowledge about C#... but unclear what exactly. Asking if line of code will be executed at all when it simply written in the code without any conditions around it does not make much sense to me. – Alexei Levenkov Sep 07 '16 at 18:16
  • `"I simply wanna know if this code [...] would be executed"` - Why *wouldn't* it? What would prevent that line of code from executing? – David Sep 07 '16 at 18:17
  • When you initialize the dictionay yes it will call the construtor of the View Model, if you want the to happen when you access the dictionary instead, you can create a dictionary of Type `>` and just invoke a func which will return a new ViewModel () => {new ViewModel();} – johnny 5 Sep 07 '16 at 18:20
  • Yes, those constructors are getting invoked. Whenever you call `new Class()` you are invoking the Class' parameterless constructor. If one does not exist, you will get a compilation error. So your first line declares, instantiates and initializes the dictionary. Then, the next 3 lines add 3 `KeyValuePair`s of `string`=>`ViewModelBase` by invoking the 3 constructors for your 3 models and returning an instance of the object to the Dictionary's `Add` method, one at a time. – Tom Sep 07 '16 at 20:38

5 Answers5

1

NOTE When you initialize the dictionay yes it will call the construtor of the View Model, if you want the to happen when you access the dictionary instead, you can create a dictionary of Type <string, Func<ViewModel>> and just invoke an Function which will return a new ViewModel () => {new ViewModel();}

There are a few ways to initialize a dictionary in c#

  1. You can use the syntax you are using which will create the dictionary then initialize the values using add.

    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;
    }
    
  2. You can create it using initializers the C#5 and older way would be like this:

    public static Dictionary<string, ViewModelBase> LoadDictionary()
    {
         return new Dictionary<string, ViewModelBase>() { 
             {"LoginView", new LoginViewModel()},
             {"SignUpView", new SignUpViewModel()}, 
             {"ContactListView", new ContactListViewModel()} 
         };
    }
    

    Note this is risky because you can initialize a dictionary with the same key which will cause an error

This way under the hood calls the Add method what is even more interesting is that you can overload the Add method to modify the way you add things to the dictionary, meaning if you create an overload for Add which takes (int, ViewModelBase) and say you called int.ToString() internally you can use int's in the initializer as well.

  1. In C# 6.0 and greater there is a new way to initialize dictionaries which is like this:

    Dictionary<string, Customer> cList = new Dictionary<string, Customer>()
    {
       ["LoginView"] = new LoginViewModel(),
       ["SignUpView"] = new SignUpViewModel()
    };
    

The benefit of using this way is that if you add an entry to the dictionary with the same value it will override the old value and not cause an error you can find more information on it here

johnny 5
  • 19,893
  • 50
  • 121
  • 195
0

Does the compiler first creates a constructor (parameterless ctor) and only then add my KeyValuePairs?

The compiler doesn't have to create anything. Dictionary<> has a parameterless constructor, which you're calling here:

new Dictionary<string, ViewModelBase>();

You're simply invoking the constructor, passing no parameters, and getting back an instance of a Dictionary<string, ViewModelBase>.

When I add my KeyValuePairs, are the Values also instantiated?

They're instantiated, because you're instantiating them:

new LoginViewModel()

Like any other constructor, this creates a new instance of the class.


Note that none of the code you're showing really has anything to do with class initializers. An initializer for a collection type (like a Dictionary<>) might look something like this:

Dictionary<string, ViewModelBase> tempDictionary = new Dictionary<string, ViewModelBase>() { 
     {"LoginView", new LoginViewModel()},
     {"SignUpView", new SignUpViewModel()}, 
     {"ContactListView", new ContactListViewModel()} 
 }

Which is compiled to essentially the equivalent of what you have:

Dictionary<string, ViewModelBase> tempDictionary = new Dictionary<string, ViewModelBase>();
tempDictionary.Add("LoginView", new LoginViewModel());
tempDictionary.Add("SignUpView", new SignUpViewModel());
tempDictionary.Add("ContactListView", new ContactListViewModel());

It's not entirely clear where your confusion is on the subject, but essentially all any of this code does is create instances of objects.

David
  • 208,112
  • 36
  • 198
  • 279
0

Yes, the tempDictionary.Add("LoginView", new LoginViewModel()); expression will create a new instance of the LoginViewModel class, even if you never tried to access the LoginView key of the tempDictionary dictionary object.

Botond Botos
  • 1,202
  • 13
  • 20
0

Going off your comment:

@Jonesopolis I Simply wanna know if this code:

tempDictionary.Add("LoginView", new LoginViewModel()); 

would be executed and call the LoginViewModel constructor even if I did not call the "LoginView" key in any other part of my program.

this code is the same as:

var vm = new LoginViewModel();
tempDictionary.Add("LoginView, vm);

the expression that constructs the object (new LoginViewModel()) is executed first, then the resulting value is passing into the Add method on the dictionary. So yes, your object is constructed before being passed into the dictionary.

You could write a very simple program to have tested this yourself.

Jonesopolis
  • 25,034
  • 12
  • 68
  • 112
0

I Simply wanna know if this code:

tempDictionary.Add("LoginView", new LoginViewModel());

would be executed and call the LoginViewModel constructor even if I did not call the "LoginView" key in any other part of my program.

Yep, the constructor is called right then and there in the code. If you want to lazy load them, you can try the Lazy<T> class as well.

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()));

Then get your models by accessing the Value property on your Dictionary values.

var modelKey = "LoginView";
var myModelFromKey = deferredConstructionDict[modelKey].Value;

ORIGINAL POST:

I think there's a fundamental misunderstanding in your question that isn't addressed in the other answers.

How does Dictionary work when we initialize a class within as a value?

I believe what you mean by "class within" is that your Dictionary<string, ViewModelBase> type contains a type ViewModelBase as the 2nd generic type. The Dictionary<T,U> type is a generic type, which has special rules in C#. C# doesn't call the constructor of the type T or U when it calls the constructor of Dictionary<T, U>, it simply understands the type information about T and about U so that the runtime knows how to deal with the objects stored in the dictionary when you reference them later.

Basically generic types (in your case I'm referring to string and ViewModelBase) are placeholders for the runtime, and the way C# deals with them is that when a generic is used, the runtime should be able to figure out how to handle them no matter what type is used when you create an instance of the generic type. This means that, even if it did makes sense to do so, the Dictionary<T,U> constructor can't call new ViewModelBase() above because not all types have a constructor! (ICloneable for instance). In C#, a type is simply some information it knows about an object which it uses both at compile and runtime to determine what to do with it.

Does the compiler first creates a constructor (parameterless ctor) and only then add my KeyValuePairs?

Nope. You write constructors, and you call constructors. C# calls constructors implicitly only in rare cases (using reflection, for instance).

Community
  • 1
  • 1
Frank Bryce
  • 8,076
  • 4
  • 38
  • 56