While I was at DevConnections last week, I watched an interesting demo showing off Visual Studio's extensibility. In the demo the visual studio shell is being used to edit Lua script; the scripting language used by World of Warcraft for designing custom interfaces. The demo showcased Visual Studio's flexibility and captured the audience's attention pretty well.
The speaker added an interesting interface into World of Warcraft which showed images and played sounds when she killed enemies. I think it will be nice to use Visual Studio for almost any programming language. The familiar environment will make things easier. Perhaps more add-ons for Visual Studio will be available in the near future. This WoW Lua add-on is supposed to be available on CodePlex soon.
I don't play World of Warcraft, so I will be waiting to see what extensions other people will decide to make.
A couple of weeks ago Steve Smith and I (Brendoneus) released SimpleCMS as an open source project on CodePlex. SimpleCMS is, as the name suggests, a Simple Content Management System. It is a small ASP.NET 2.0 Plug-in which allows dynamic creation of simple pages. I've not gotten much opportunity to work on it in a long time, but I did manage to get enough time to put it on CodePlex.
The main goal of SimpleCMS is to be simple. It isn't designed to support a lot of features or be bloated. It is designed to be lightweight. I recommend checking it out if you get the chance. The project could use some more development, and if I get the free time I'll try to work on it a bit.
Let me know what you think about SimpleCMS.
One of the most important parts of software development is memory management. Memory management is important for every software application. If one is to write a well developed software application, one must have a fair bit of knowledge in the area of memory managament. It is important to understand the underlying technology which allows programs to function. There are many aspects of programs which come into play often in .NET applications; variables, functions, garbage collection.
Understanding Garbage Collection, Heaps, and Stacks
When using a language with a heap, it is important to understand that memory will be allocated dynamically. This is separate from where the basic program memory resides; the stack. On the stack memory builds as the program executes. Local variables are stored with the function information. This is the memory used in pretty much every language. When a heap is involved there is basically an area of memory where variables may be dynamically defined and only references to these variables are stored as pointers on the stack.
When the variable is out of scope or removed it is merely the reference to the variable which is removed. A garbage collector will come by later to free the memory for later use. Whenever there is not enough room to allocate memory in the heap the garbage collector wil come and clear unused memory.
Understanding Variable Types
There are basically two types of variables; value and reference. The value types tend to be the simpler variables and the reference types tend to be the more advanced variables. Some examples of value types are enums, ints, doubles, bools, chars, and structs. Some reference types are arrays, lists, and classes. The value types are the ones stored locally with the stack and the reference types are stored in the heap, and a reference to them is stored on the stack. When using the new keyword, memory is allocated on the heap and a referenced object is created.
Passing Parameters to Functions.
When passing variables as parameters to functions, it is important to understand the two main ways in which these variables may be passed. Variables may be passed by reference or by value. Passing by value means that we make a copy of the local variable and use that in the function. This means that our value type variable will be copied and if we use a reference type it means that only the reference will be copied. This means that we will still be accessing the same location in the heap even if we pass by value. By using the ref keyword you may pass a parameter by reference. This means for a value type you are able to just pass a reference to the original value. Do not pass a reference type by reference, because it will just make a reference to the reference to the value and that will slow things down for no reason. Passing by reference is a good idea if the value is large, so with a large struct you may want to pass by reference instead of copying all of the data.
Generics vs. Objects
When using parameters of type object, boxing and unboxing is used to take the variable and changing it to and from object. This seems pretty easy because one can simply add (object) when passing the parameter. The problem here is that this will create a new instance of an object. This means we will be making a copy of the variable instead of just using a reference to the variable. This will take time, and will also allocate extra memory which will need to be collected by the garbage collector later. This will also decrease the performance of our program. This is why it is important to use generics to prevent this performance hit. When we use generics we do not have to make a copy of the value, we merely pass a reference to the original value.
Be careful, and try to use Generics whenever possible. Your memory will thank you.
Temporary tables and table variables can be used in pretty much the same way. One question which is asked, "Which one is better". To answer that it is important to understand a few of the differences between the two. Once we understand how these two types of tables are different we will better understand which we need to use when.
Creating a temporary table is very similar to creating a regular table. In order to do this we use the following code
create table #myTempTable (columnA typeA, columnB typeB, ...)
Table variables are created as regular variables are declared. The type of the variable is just defined as a table.
declare @myTableVariable table (columnA typeA, columnB typeB, ...)
Scope is another important factor to consider. With a table variable its scope is similar to other variables. A temporary table however does not share this scope, and can even be accessed in a stored procedure called by your code. This is one very nice feature of temporary tables over table variables.
Table variables do not record any entries in transaction logs. Temporary tables do store their transactions. Depending on what you are trying to accomplish this can be a benefit for either of the two types of tables. It is often very important to keep track of the transaction log, and in these instances a temporary table is far better for your needs, but other times the transaction log is simply unnecessary and a table variable would be the optimal choice.
I've heard of great performance gains in temporary tables because of their ability to be pre-compiled. I've also heard that table variables are faster than temporary tables in general. I believe this has to do with the nicely defined scope of table variables. Because of this they may use fewer resources than temporary tables. An example of this is the transaction log I mentioned earlier.
For the most part a table variable is just as flexible as a temporary table, and in most instances it also out performs temporary tables in my experience.
One thing to watch out for when using temporary tables is the possibility of causing your store procedure to recompile. Microsoft has a Knowledge Base Article about Troubleshooting stored procedure recompilation which discusses this danger. Table variables will not cause this problem.
I would recommend the use of table variables for everyday use, and only using temporary tables when they're required. Instances of this include the need for a transaction log. Or any time you feel like writing extra lines of code simply to perform cleanup on your temporary table. But that is just my $0.02 on this issue.
Happy SQL writing!
One question that seems to come up often in the asp.net forums is from people who are trying to access controls within controls using templates. LoginViews and CreateUserWizard controls are two commonly used templated controls. These templated controls don't actually have their contents known until run-time because it is dependant on something else; data from a database, user permissions, etc.
Since this information is not known you can't just access the inner controls as you would normal controls, because it is not known until run-time what the controls are. You will get compiler errors if you try to access them. The easiest way to get the controls you need is to use a recursive find control function. Steve Smith has blogged about Using a Recursive Find Control as well as about a very important Code Optimization for using a recursive find control.
The cool thing about the recursive find control is that it will dig down into the controls collection of a control you specify looking for the control you are looking for. It is great for templated controls, because it is a lot neater than trying to statically go after it like this.
Bad Code Do Not Use This
Label Label1 = LoginView1.Controls[2].Controls[2].Controls[1].Controls[3].FindControl("Label1") as Label;
The problem with the above code is that if you move anything you'll break the code. It is not very stable, and is even hard to tell what is being done. Do not worry there is a better way of handling this. A recursive find control is an expensive operation, and this is why Steve's code optimization is important. You don't want to execute the find control more times than needed.
Good Code Use This
public static System.Web.UI.Control FindControl(System.Web.UI.Control start, string id)
{
System.Web.UI.Control foundControl;
if (start != null)
{
foundControl = start.FindControl(id);
if (foundControl != null)
return foundControl;
foreach (Control c in start.Controls)
{
foundControl = FindControl(c, id);
if (foundControl != null)
return foundControl;
}
}
return null;
}
The above code will find controls nested within templated controls for you. This code will probably go in one of your class libraries where you keep utility functions. When you're calling this function, I would recommend you call it within a property as in Steve's optimization. The following code shows how you would do the previous example in a better way.
Good Code Use This
private Label _label1 = null;
private Label Label1
{
get
{
if (_label1 == null)
{
_label1 = Utilities.FindControl(LoginView1, "Label1") as Label;
}
return _label1 ;
}
}
This allows you to access the control as you normally would try. You can just type in the name of the property and it will let you use it as if it were the control and there were no templated control there at all. Makes working with LoginViews and CreateUserWizard controls.
Repeating templated controls such as the GridView can also benefit from this functionality, but you need to be more careful with them because there is a control with the name you're looking for in each row of the repeating control. Make sure when using this there that you get the correct row first, and only search within that row.
Have fun finding your controls.