Solved

3rd C# related question

Posted on 2013-10-24
17
368 Views
Last Modified: 2013-10-25
The course I am taking first does the following

public class BasicWebPart : WebPart
    {
        Button btn = null;
        protected override void CreateChildControls()
        {
            btn = new Button();
            btn.Text = "Click Me";
            btn.Click += new EventHandler(btn_Click);
            Controls.Add(btn);
            var literal = new LiteralControl(@"<p>Some text here</p>");
            Controls.Add(literal);
        }

        private void btn_Click(object sender, EventArgs e)
        {
            btn.Text = "Clicked";
        }
    }

Then, when it comes time to demonstrate how to use the RenderControls method to make some last second adjustment to the order in which the controls are rendered, he does this


public class BasicWebPart : WebPart
    {
        Button btn = null;
        LiteralControl literal = null;
        protected override void CreateChildControls()
        {
            btn = new Button();
            btn.Text = "Click Me";
            btn.Click += new EventHandler(btn_Click);
            Controls.Add(btn);
            literal = new LiteralControl(@"<p>Some Text</p>");
            Controls.Add(literal);
        }

        protected override void RenderContents(HtmlTextWriter writer)
        {
            literal.RenderControl(writer);
            btn.RenderControl(writer);
        }

        private void btn_Click(object sender, EventArgs e)
        {
            btn.Text = "Clicked";
        }
    }

The difference is the first he added LiteralControl literal=null outside of the CreateChildControls scope,  I'm guessing it is for persistence and i understand why he does not have to say
var literal = new LiteralControl(@"<p>Some text here</p>");
and can now instead say
literal = new LiteralControl(@"<p>Some text here</p>");
Inside of CreateChildControls, because the type is already declared.

But why does he change his type from the generic "var" to "LiteralControl" when he moves the type declaration outside of CreateChildControls? Is it because he has to call the RenderControl method of literal inside of RenderContents? Am I to assume that if he uses var instead of LiteralControl, that he cannot then call RenderControl? I think i understand why, but I need to make sure that I do

But I don't understand how writer automatically will write out what is designated in CreateChildControls when the RenderControl method is called within RenderContents

If he needs to create btn and literal outside of CreateChildControls for resuse in RenderContents because they will not persist after CreateChildControls is finished, then how does writer know what to write out?
0
Comment
Question by:BobHavertyComh
  • 7
  • 6
  • 3
  • +1
17 Comments
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
Comment Utility
The whole var thing is something I first experienced when using Resharper a few years back. It's quoted as being good style though functionally equivalent; stackoverflow.com/questions/4868477/why-should-i-use-var-instead-of-a-type

However IMHO it's a retrograde step from being really clear what you want to achieve by stating a clear type up front. Back in my VB days Variants were considered evil, so why bring them back in a decent language like C#?

I'm not sure I get the second part of your question. The values to be written out can be obtained easily because the button and the literal will have instances with properties all set. The writer itself isn't something you create yourself, it's more of an address to the writer that has been created by the framework behind the scenes. Your Controls have a RenderControl method and you just provide the address to the writer that you've been given as a RenderContents argument.
0
 
LVL 9

Author Comment

by:BobHavertyComh
Comment Utility
First part answered, and I will probably just use the actual type itself as a good habit.

Let me clarify the second part. Since the actual objects are instantiated in CreateChildControls and in CreateChildControls the value for their text is set, aren't those actual instantiated objects and the value they contain gone after CreateChidlControls? There must be some special relationship between CreateChildControls and RenderContents that allows these instantiated objects to persist, as far as the theory that I know goes. Otherwise, those objects should no longer be relevant after CreateChildControls is finished and RenderContents is called. So there is either a misunderstanding that I have or a piece of the puzzle that I am missing.
0
 
LVL 31

Assisted Solution

by:Jamie McAllister MVP
Jamie McAllister MVP earned 200 total points
Comment Utility
I believe there is a slight misunderstanding about scope. The lifetime of the object instance doesn't depend on where it was instantiated, but where it was declared.

It's declared outside the methods so it can exist across those different methods without going out of scope.

If it was declared (and instantiated) in one of the methods it could not exist when those methods finished their work. It's declared outside so the method finishing doesn't destroy the instance.

The other way it can be destroyed if is the pointer to the object is set to null in a method (though this doesn't instantly destroy it, it just makes it a candidate for the garbage collector to clean it up). Some objects (but not all) expose a .Dispose() method which can also be used to destroy an object instance.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
Back in my VB days Variants were considered evil, so why bring them back in a decent language like C#?
I hope I'm misunderstanding what is being said here, but var is not equivalent to VB's Variant type (which is more akin to object in .NET). var tells the compiler to infer the type of the variable from whatever the type of the thing on the right side of the assignment operator is.

It is convenient to use var when working with LINQ, because LINQ usually ends up creating a lot of anonymous objects, for which the compiler generates, and you would not know, the type. It is generally a bad idea to use var when the thing on the right is a function call.

e.g.

var someResult = SomeFunction();

It's not clear (just by reading) what the type of someResult is. If the thing on the right is an object instantiation:

e.g.

var someResult = new string("hello world!");

...then it's easy to see what the type of someResult is.

The lifetime of the object instance doesn't depend on where it was instantiated, but where it was declared.
Well, an object doesn't exist before it is instantiated, so I would say that it does depend slightly on where it was instantiated. If you are talking of variable scope, then that would make sense.

The scope of a variable doesn't depend on where it was instantiated, but where it was declared.
0
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
Comment Utility
I'm not saying that var is the same as variant. I'm saying that if the intent is known why not state it?

Take your point about instantiation, but scope is the concept I'm hoping to impart there.
0
 
LVL 9

Author Comment

by:BobHavertyComh
Comment Utility
OK, so both of your have some good points. and I will award both of you points for your efforts, and I thank you both for your efforts as I am always appreciative when someone gives their time to help me out.

But in regard to the scope issue I need some clarification, I have always understood that if I create a variable or even instantiate an object outside of the scope of a method, the variable or even instantiated object will obviously persist. And in the case of instantiating an object, if it is globally instantiated (for lack of a better word), then it will persist and any values set to it at the global level will persist unless changed by a method. That's easy to understand.

But in the case above, the variable and type is being declared globally, and there is no instantiation nor value being set at the global level, it is merely declared as a variable of a certain type.

But the object is being instantiated within CreateChildControls, so therefore when CreateChildControls in finished, it is my understanding that this object and any properties that might be set in it are gone unless createChildControls returns a value that writes to either a globally declared variable, or a property of a globally instantiated object.

So if true, how do these two controls created in CreateChildControls persist unless there is some special relationship between CreateChildControls and RenderContents? And also, RenderControls is not just controlling or changing the order in which these controls are written out, it is also writing the property values that were set in CreateChildControls. So how can it do that unless the object and property values set for it persist outside of CreateChildControls? It can't be invoking the global variable that is originally set to null to my knowledge because it will never have a value if CreateChildControls does not return a value that writes to it, and in this case it seems like it does not as there is no return value declared in the method declaration and no return statement within it.

And yet RenderContents seems to not only magically know about these objects when they should no longer exist, it even knows about their property values. So there has to be some sort of special, magical persistence between these two methods that I do not know about, but should know about.
0
 
LVL 15

Expert Comment

by:colly92002
Comment Utility
A "var" is an anonomous type, its actual type is infered by the compiler.  Therefore if the class level variable was declared as a "var" it would stuggle be able to infer the type you actually want (LiteralControl) from the  value you delare it as ("null" !).

vars are very useful (and essential for LINQ) but I see them all the time in places that I don't really understand - in your example I can't see why you wouldn't declare both examples as LiteralControls.  Pehaps your tutor just wanted to show you the two differnt ways of declaring the same thing?
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
@colly92002

A "var" is an anonomous type
No it is not, though the resulting type inferred by the compiler can be an anonymous type.

its actual type is infered by the compiler.
Yes, as I mentioned above.

Therefore if the class level variable was declared as a "var" it would stuggle be able to infer the type...
That is a moot point as the compiler does not allow class-level var declarations.
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
@BobHavertyComh

I think you are confusing scope and object lifetime. The scope of a variable is all the places within code that that variable can be seen/accessed. Scope says nothing about what the variable does or does not point to. Object lifetime is how long an object is considered to be an active, usable object. Object lifetime starts at instantiation and ends once the last reference to that object has been destroyed. (As JamieMcAllister pointed out, this does not necessarily mean that--in a managed environment--the object has been completely purged [due to garbage collection], but it should mean that you can no longer *safely* use the object at that point.)

In .NET, once all references to an object are released, the object becomes eligible for garbage collection. References to the object can exist even outside the scope an arbitrary variable that points to the object. This is due to the behavior of reference types, which are simply pointers to the actual data in memory. Anything defined as class will be a reference type. You can have reference-type variables scattered throughout your project, and they could all be pointing to the same object. So the object's lifetime is longer than the scope of some of these variables.
0
 
LVL 9

Author Comment

by:BobHavertyComh
Comment Utility
Hi colly, I agree with you. This is what a video course instructor is doing. The curious part is that at first in the demo he does what is  the first code section in my first post and it uses var within the class and no global declaration. Then, he changes the code and the changes are represented by my second block of code in my first post. so that he can demo how to use RenderContents to change the order that the controls will display in and he declares the literal variable globally and then merely references it in the class when he instantiates it and does not declared type within the class because it is already declared globally. But he changes the declaration from var to LiteralControl when he declares it globally. I'm guessing he moves the declaration to the global level so that it can be reused in RenderContents, but for some reason, when he declares it globally, he uses the specific type of LiteralControl rather than var, and I was wondering if he did that because if he declared it as var rather than Literal, he could not use the RenderControl method that he is using within the added RenderContents method that he added in the second block of code I posted. Otherwise, i don't see why he would do that, but a lot of times, this guy actually has a reason for what he is doing that he does not bother to explain because he assumes that you are a very experienced C# developer and that you know why.
0
 
LVL 9

Author Comment

by:BobHavertyComh
Comment Utility
I think you are confusing scope and object lifetime. The scope of a variable is all the places within code that that variable can be seen/accessed.

Yes, but in the code, the variable has no value when it is set outside of CreateChildControls. A value is only set for a property when that variable is used to instantiate an object within CreateChildControls. And there is nothing in CreateChildControls method that returns a value after it is finished to set a value for the variable initially declared outside of it. So if the property value of "<p>Some Text</p>" is set when the object is instantiated, and the CreateChildControls method returns no values that can be used to set any values of the initial variable declared outside of CreateChildControls, how do the property values that are only set within the object instantiation within CreateChildControls persist to later be used with RenderContents if the object itself is supposed to be destroyed after CreateChildControls is finished?

I know I am being kind of stupid, and I am guessing that you have already given me that answer, but I didn't understand it. So I hope I can at least explain to you what my confusion is and where my mistake is. Sorry for being a little dense.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
...when he declares it globally, he uses the specific type of LiteralControl rather than var, and I was wondering...
As I mentioned above, var cannot be used at the class level. var is restricted to local declarations only.

See:  http://msdn.microsoft.com/en-us/library/vstudio/bb383973.aspx

Beginning in Visual C# 3.0, variables that are declared at method scope can have an implicit type var.
0
 
LVL 74

Accepted Solution

by:
käµfm³d   👽 earned 300 total points
Comment Utility
how do the property values that are only set within the object instantiation within CreateChildControls persist to later be used with RenderContents if the object itself is supposed to be destroyed after CreateChildControls is finished?
The object is not destroyed until the last variable (in scope) referencing that object is discarded. If you have a class-level variable pointing to some piece of data that is instantiated within one of the member methods, then that object is now referenced for the lifetime of the containing class instance, or until some other method causes the variable to stop pointing to the object (by assigning it null or a different instance of the object's class).
0
 
LVL 9

Author Comment

by:BobHavertyComh
Comment Utility
Let me see if I can explain this better. So if a variable is first created outside of a method, and if inside the method, that outside variable is used to instantiate an object, does that mean that since it used a variable outside of the method to instantiate an object within the method, then this instantiated object and the properties that are set within the method persist after the method that it is instantiated in finishes? And is it because it used the variable outside the method for the instantiation of the object within the method that the instantiated object is now tied to the variable outside of the method and it's existent and set properties now persist through the outside variable?

I'm finding it hard to even explain my question correctly, and thanks for the patience. Sorry for the thickness.
0
 
LVL 9

Author Comment

by:BobHavertyComh
Comment Utility
"The object is not destroyed until the last variable (in scope) referencing that object is discarded."

Ok, that seems to be what I was just getting at in my last post above. It's because the object was instantiated using a variable outside of the method for it's instantiation, that it persists until the variable used to create the instantiated object goes away. So the object is always tied to the variable that it used for instantiation, and it's existence, and persistence of property values will be dependent upon the scope of the variable that it used for instantiation, not the scope where it was instantiated. Do I finally have this right? Boy, I feel really embarrassed and thick. Sorry about that. I'm normally not this stupid.
0
 
LVL 74

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 300 total points
Comment Utility
So if a variable is first created outside of a method, and if inside the method, that outside variable is used to instantiate an object, does that mean that since it used a variable outside of the method to instantiate an object within the method, then this instantiated object and the properties that are set within the method persist after the method that it is instantiated in finishes?
Your terminology is slightly off, but yes. (I'll explain what I mean later, if you prefer.)

And is it because it used the variable outside the method for the instantiation of the object within the method that the instantiated object is now tied to the variable outside of the method and it's existent and set properties now persist through the outside variable?
Er, kind of. You have to understand what a reference type is. When you have a reference type, the variable points to the data in memory, it does not actually contain the data (whereas with a value type the variable does contain the data). Try this picture out; assume everything pictured is a reference type:

Screenshot
Each colored line is a reference. You see that two variables have references to objects in memory. (There should be a 3rd line for Controls, but the class itself has that variable [in a designer-generated file that you won't see] so I left it out.) You can see that Controls itself has two references: one to each other object in memory. This is a result of your two Controls.Add calls. Now, because Controls has a reference to LiteralControl, the fact that var literal is a local variable has no bearing on LiteralControl being destroyed--there is still a remaining reference to it by way of Controls.

Now, since you declared btn at the class level, it is scoped to the entire class. That means any method can see it. So CreateChildControls can instantiate btn to the Button Instance that is in memory (as it does). Since btn is class level, it is not destroyed once CreateChildControls ends. Since it is not destroyed, it continues to point to what it was assigned:  the Button Instance.

Furthermore, literal is destroyed when CreateChildControls ends because literal is a local variable. However, the thing it points to is not destroyed because Controls is holding on to a reference to that object.

On a different note, don't stress about not getting it right away. We are volunteering at a Q&A site. If we didn't want to answer questions, we wouldn't be here  ; )
0
 
LVL 9

Author Closing Comment

by:BobHavertyComh
Comment Utility
Thanks everyone, I get it. Sorry for being so thick. I think the last thing that I said was the correct understanding. Basically, it does not matter where the object is instantiated, it matters where the variable that holds the instantiated object is declared or what scope it has. I was forgetting that the object instantiation was being put into the variable and that variable has a class scope, not a method scope. I didn't exactly know how to split the points up as there were so many good answers, that shouldn't have been needed if I wasn't being so thick, So I did the best I could splitting it up, but thank you for the effort and patience. I don't know what my block was, but it is actually very simple to understand. I think i was just forgetting that the class scoped variable value was being set during object instantiation within the method, but it's life is at the class scope, not the method scope.
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Suggested Solutions

Note:  There are two main ways to deploy InfoPath forms:  Server-side and directly through the SharePoint site.  Deploying a server-side InfoPath form means the form is approved by the Administrator, thus allowing greater functionality in the form. …
Just a quick little trick I learned recently.  Now that I'm using jQuery with abandon in my asp.net applications, I have grown tired of the following syntax:      (CODE) I suppose it just offends my sense of decency to put inline VBScript on a…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now