ASP.NET MVC takes advantage of many advanced features of the C# and VB.NET languages. Some of these features were not introduced into these languages until C# 3.0 and Visual Basic 9.0. This appendix provides you with a brief overview of these new language features.
Both C# and Visual Basic can infer the type of a variable when you create a local variable. For example, the following line of code creates a new string variable named message
with the value "Hello World!"
:
(C#)
var message = "Hello World!";
(VB)
Dim message = "Hello World!"
Notice that you do not need to specify the type of the message variable. The compiler figures out the type from "Hello World!"
automatically.
There are no performance drawbacks from using type inference. The type is inferred at compile time and not runtime. In particular, using type inference does not result in late binding.
Type inference is a good way to remove some of the redundancy in the C# language. Consider the following statement:
(C#)
ArrayList countries = new ArrayList();
(VB)
Dim countries As New ArrayList()
In the case of C#, the type of the countries variable is specified twice: on both sides of the = sign. Using type inference removes this redundancy with no drawbacks in performance:
(C#)
var countries = new ArrayList();
Object initializers provide you with shorthand syntax for creating a new object and setting one or more properties on the object. Imagine, for example, that you want to create an instance of a Customer
class and set the FirstName
and LastName
properties. Normally, you would have to write the following code:
(C#)
Customer customer1 = new Customer();
customer1.FirstName = "Scott";
customer1.LastName = "Guthrie";
(VB)
Dim customer1 As New Customer()
customer1.FirstName = "Scott"
customer1.LastName = "Guthrie"
By taking advantage of the new object initialize syntax, you can reduce the three lines of code to a single line:
(C#)
Customer customer1 = new Customer() { FirstName="Scott", LastName="Guthrie"};
(VB)
Dim customer1 As New Customer() With {.FirstName = "Scott", .LastName = "Guthrie"}
Anonymous types give you a compact way to define a new class and create a new instance of the new class at the same time. For example, the following line of code both creates a new type of class and instantiates an instance of the new class at the same time:
(C#)
var product1 = new { Name = "Netbook", Price = 344.99m };
(VB)
Dim product1 = New With {.Name = "Netbook", .Price = 344.99}
This single line of code is equivalent to first creating a new class:
(C#)
(VB)
And then creating an instance of the new class:
(C#)
var product1 = new Product {Name="Netbook", Price=344.99m};
(VB)
Dim product1 = New Product With {.Name = "Netbook", .Price = 344.99}
Obviously, using anonymous types takes far, far less typing to accomplish the same work.
Two anonymous types that have the same properties, in the same order, are the same type. For example, product1
and product2
are the same type:
(C#)
(VB)
However, sandwich1
, sandwich2
, and sandwich3
are all different types; the order of the properties is different in the case of sandwich1
and sandwich2
:
(C#)
(VB)
Anonymous types are used extensively in the ASP.NET MVC framework. For example, you can specify a set of HTML attributes when using an HTML helper by using an anonymous type:
(C#)
<%= Html.TextArea("Comments", new {cols="50", rows="10"}) %>
<%=Html.TextArea("Comments", New With {.cols = "50", .rows = "10"})%>
When this Html.TextArea()
helper renders an HTML textarea
, the textarea
is rendered with cols="50"
and rows="10"
attributes.
When creating anonymous types with Visual Basic, you can use the Key
keyword to mark certain properties as key
properties. A key
property is used to determine when two instances of the same anonymous type are equal. If two instances of the same anonymous type have the same values for their key
properties, then the two instances are equal.
Reference types, such as a string, can accept the value null
(Nothing
). Value types, such as an integer
or DateTime
, normally cannot accept the value null
(Nothing
).
By taking advantage of nullable types, you can assign the value null
to a value type like an integer or DateTime
. For example, the following line of code creates a nullable DateTime
named dateReleased
:
(C#)
DateTime? dateReleased = null;
(VB)
Dim dateReleased As DateTime? = Nothing
The question mark indicates that the dateReleased
variable represents a nullable type instead of a value type.
You can use nullable types with method parameters. For example, you can use a nullable type with an ASP.NET MVC action parameter like this:
(C#)
(VB)
You can invoke this action using either of the following URLs:
/Home/Index
/Home/Index/22
Because the Index
action accepts a nullable parameter, invoking the action without supplying a parameter does not result in an error.
Notice how the action uses the HasValue
and Value
properties. You use HasValue
to determine if a nullable type has the value null
(Nothing
). You use the Value
property to get the non-nullable type from the nullable type.
Extension methods enable you to add new functionality to an existing class without deriving a new class. In other words, extension methods enable you to extend an existing class with new methods.
In the ASP.NET MVC framework, all the helper methods are implemented as extension methods. For example, the Html.TextBox()
helper method is an extension method that extends the HtmlHelper
class.
You create extension methods in different ways when using C# versus Visual Basic. When working with C#, you create an extension method by creating a static class with a static method.
Notice that the first parameter is qualified by the this
keyword. The this
keyword indicates that the Button()
extension method extends the HtmlHelper
class. The Button()
method becomes a method of the HtmlHelper
class.
You create an extension method with Visual Basic by creating a module:
(VB)
Notice that the Button()
method is decorated with the System.Runtime.CompilerServices.Extension
attribute.
To use an extension method, you must remember to import the namespace of the extension method. For example, if you want to use the Html.Button()
helper method in a view, then you must import the Helpers
namespace in the view using the Import
directive like this:
<%@ Import Namespace="MvcApplication1.Helpers" %>
After you import an extension method, the extension method appears in Intellisense just like any other method (see Figure A.1).
A generic is a class, structure, interface, or method that accepts one or more type parameters. If you have worked with generic collections, you are already familiar with generics. For example, the generic List
collection, which you can use to represent a list of items of a particular type, is a generic class:
(C#)
var shoppingList = new List<string>();
(VB)
Dim shoppingList As New List(Of String)()
When you create a generic List
, you specify the type of item that the list represents. In the preceding code, the List
represents a list of strings.
Generics is another language feature that is used extensively in the ASP.NET MVC framework. For example, the ViewPage
class—the base class for views—is a generic class. When you create a view, you supply a generic type parameter for the ViewPage
class in the <%@ Page %>
directive like this:
(C#)
In this case, we actually have two generic type parameters. Both the ViewPage
class and the IEnumerable
interface accept a generic type parameter.
The generic type parameter is used by the ViewPage
class to cast the Model
property to a particular type. In this case, the Model
property is cast to a collection (IEnumerable
) of Product
items.
A lambda expression provides you with a compact way to express a function. You can use a lambda expression to represent a function like this:
(C#)
x => x * 2
(VB)
Function(x) x * 2
This expression represents a function that accepts a parameter named x
and times x
by two. This lambda expression is equivalent to the following function:
(C#)
(VB)
Lambda expressions are used most often with LINQ. See the next section to learn about LINQ.
LINQ (Language INtegrated Query) enables you to perform operations on a set of objects. The objects could be a set of database records. By taking advantage of LINQ, you can write all your database logic within the C# or Visual Basic language, and you never need to write any SQL code again.
The System.Linq namespace contains two classes named Enumerable
and Queryable
. The Enumerable
class contains a set of extension methods for the IEnumerable<T>
interface. For example, the Enumerable
class includes the following extension methods (this is not even close to being a complete list):
• Average()
• Count()
• First()
• Last()
• Max()
• Min()
• OrderBy()
• Select()
• Sum()
• Where()
Because these are extension methods on the IEnumerable<T>
interface, you can use these methods on any class that implements the IEnumerable<T>
interface including the generic List
class:
(C#)
(VB)
This code creates a generic List
class that represents a set of products. The Enumerable
extension methods are used to retrieve a set of products where each product has a price greater than $50.00 and the products are ordered by name. Therefore, you get the following products in the following order: Chair
, Laptop.
Notice that the LINQ methods use lambda expressions. For example, the Where()
method accepts a lambda expression (a function) that returns a Boolean value. The lambda expression is used to filter the set of products.
The Queryable
class contains a similar set of extension methods; however, these methods extend any class that implements the IQueryable<T>
interface.
Both the Microsoft Entity Framework and Microsoft LINQ to SQL represent database tables with classes that implement the IQueryable<T>
interface. That means that you can use these extension methods with either technology.
For example, here is how you would retrieve a set of database records by using the Queryable
extension methods with the Microsoft Entity Framework:
(C#)
(VB)
The query retrieves all the movies that have a title that starts with the letter T and orders the results by the date the movie was released.
Instead of using the Enumerable
or Queryable
extension methods directly, you can use the new query syntax language features introduced into the C# and Visual Basic languages. In other words, there are two ways to execute a LINQ query: method syntax and query syntax.
The following code uses query syntax to retrieve the same set of movies that we retrieved earlier using method syntax:
(C#)
(VB)
You might find query syntax more readable than method syntax. There is no difference in performance. Your choice between method and query syntax is purely a preference issue.
When you use LINQ against a database, the query is translated into a SQL query and executed. When you retrieve a set of database records, the SQL query is not executed until you actually start iterating through the results (for example, by using a for
each loop).
This is an important point: LINQ does not load an entire database table into memory and then perform operations on the loaded data. Instead, LINQ waits until the last possible moment to execute a query. Just before you start to iterate through the results of a query, LINQ analyzes your query and converts it into the most efficient SQL query possible and then executes the SQL query against the database.
3.22.249.48