spiderplant0
spiderplant0

Reputation: 3952

Double angular brackets in ASP.NET C# MVC4

While trying to understand TextBoxFor() I came across this definition in MSDN....

TextBoxFor<TModel, TProperty>(HtmlHelper<TModel>, Expression<Func<TModel, TProperty>>, IDictionary<String, Object>)

Is this just a generic class, or is it somethign else, or is it non-c# ?

(The angular brackets within angular brackets is throwing me of)

And how do you interpret it (a link would be fine - as long as its ok for beginners to C# etc).

Upvotes: 1

Views: 1140

Answers (4)

JimmiTh
JimmiTh

Reputation: 7449

A class with nested generic type parameters.

The inner part:

Func<TModel, TProperty>

A delegate, referencing ("describing") a function that takes the generic type TModel as an argument and returns a result of generic type TProperty, e.g.:

TProperty MyFunc(TModel model)

... which corresponds to the types in the usual argument to TextBoxFor():

model => model.Name

model is of type TModel and model.Name is of type TProperty.

The outer part:

Expression<T>

An expression tree describing a lambda expression (delegate) of the type T. The Expression<T> generic class allows you to (in simplified terms) examine the code itself at runtime rather than the result of executing it. In other words, the TextBoxFor() method can e.g. extract the actual name of the property (Name in the above example), in addition to compiling the expression and executing it to get the result.

If we simply took a Func<> as an argument, we would only be able to call the passed delegate and get the result of that call, rather than examining it in this kind of detail.

For the HTML helpers, the use of expression trees is mainly a type safe alternative to the TextBox() methods, which take the name of the property as a string.

So, in combination:

Expression<Func<TModel, TProperty>>

A parameter to TextBoxFor() that is "An expression tree describing: a lambda expression that takes a parameter of the generic type TModel and returns a property of the generic type TProperty".

The nested generics aren't limited to something as relatively advanced as expression trees. A simpler, concrete, example of nested generics is this:

Dictionary<string, List<int>>

A dictionary with strings for keys, and Lists of ints as values.

Upvotes: 1

Rob Lyndon
Rob Lyndon

Reputation: 12681

It's a class.

Expression<Func<TModel, TProperty>> encapsulates Func<TModel, TProperty>, and contains extra metadata which can be used by third parties to rebuild the Func in their own native language.

Func<TSrc, TDest> represents a function that takes TSrc as its input, and generates an instance of TDest as its output. For example, I can say:

var addOne = new Func<int, int>(i => i + 1);

and addOne would be a mapping that takes an integer and gives back that integer plus one. After you've defined it, you can then call addOne(1), and you'd expect that to give you 2.

The thing inside the brackets -- the i => i + 1 -- is a piece of syntax called a lambda. Confusingly, a lambda can be used to represent both a Func<TSrc, TDest> and an Expression<Func<TSrc, TDest>>. That is, depending on the context,

i => i + 1

represents either a Func<int, int> object or an Expression<Func<int, int>> object. This is an example (my favourite example) of homoiconicity in a language. That is, a syntax in which you can have objects of different classes represented by the same symbol, or icon.

Going back to MVC, the reason it wants an Expression<Func<TModel, TProperty>> rather than just a plan old Func<TModel, TProperty> is because it wants to know more about the property than what that property does with the model instance: it wants to know extra data such as the property name, its attributes, and what kind of error handling it uses. So you can give it something like

@Html.TextBoxFor(m => m.FirstName, ...)

and MVC will look up the property FirstName in your model and build up all sorts of HTML based on the attributes you've defined on that property.

That's more or less how it works.

Upvotes: 2

Faust
Faust

Reputation: 15404

It's just a nested generic type.

An Expression of type Func of type TModel, TProperty

Upvotes: 2

SLaks
SLaks

Reputation: 887767

This is an example of nested generic type parameters.

Expression<T> is an open generic class that takes a single type parameter.

Func<TModel, TProperty> is a concrete generic delegate type that references type parameters from the surrounding generic function.

Upvotes: 3

Related Questions