While going through the ASP.NET MVC docs I see this idiom being used alot:
new { foo = "bar", baz = "foo" }
Is this a Dictionary literal syntax?
Is it a new class/struct with the type inferred by the called function definition?
If it is how come the vars don't need a type definition, not even var?
This is an anonymous type.
Anonymous types provide a convenient way to encapsulate a set of
read-only properties into a single object without having to explicitly
define a type first. The type name is generated by the compiler and is
not available at the source code level. The type of each property is
inferred by the compiler.
http://msdn.microsoft.com/en-us/library/bb397696.aspx
Anonymous types are strongly typed. From the perspective of the common language runtime, an anonymous type is no different from any other reference type.
If two or more anonymous types in the same assembly have the same number and type of properties, in the same order, the compiler treats them as the same type. They share the same compiler-generated type information.
Anonymous types should not be passed between assemblies or even as return values from methods (possible, but rarely, rarely advisable).
Anonymous types are a convenience mechanism, e.g. when working with LINQ, such as the following projection:
LINQ Example
var result = myEnumerable.Select( o => new { foo = o.Foo, bar = o.Bar } );
// "result" is an enumerable of a new anonymous type containing two properties
Other Questions
Is this a Dictionary literal syntax?
No, though there are many similarities. ASP .Net MVC uses RouteValueDictionary and anonymous types to represent the same information in many method overloads.
how come the vars don't need a type definition, not even var?
Value types are inferred, though inference is not always possible: http://msdn.microsoft.com/en-us/library/bb531357.aspx (VB version, if someone knows the URL of the c# equivalent please update)
This is an anonymous type syntax. The type name is generated by the compiler and is not available at the source code level. The type of each property is inferred by the compiler.
This is anonymous type. That means it is returning something which has a foo property, a baz property both of string type.
Related
Given that in C# we can have the weak type var which can be of any type until it's set, is it possible to have the same var change type depending on the output of a test?
For example
var c = DBQuery.FindString("paramater", "data");
this will return NULL if the query is unsuccessful or a string if it works.
From what I can see, as FindString is has a return type of string, var c is typed as a string, despite it being null.
Is there a way to unset the typing of c so that it can then be used for
var c = DBQuery.FindInt("parameter", "data2");
Thanks
The var keyword instructs the compiler to infer the type of the variable from the expression on the right side of the initialization statement.
The keyword you are probably looking for is dynamic. The type is a static type, but an object of type dynamic bypasses static type checking. In most cases, it functions like it has type object. At compile time, an element that is typed as dynamic is assumed to support any operation.
Given this example
dynamic c = "foo";
Console.WriteLine(test.GetType());
c = 2;
Console.WriteLine(test.GetType());
Output
System.String
System.Int32
Nevertheless, I suggest you to adapt your code to avoid the dynamic type, mainly because you lose the ability to detect error at compile-time and the ability to use IntelliSense.
Additional resources
The var keyword: http://msdn.microsoft.com/en-us/library/bb384061.aspx
The dynamic keyword: http://msdn.microsoft.com/en-us/library/dd264736.aspx
You have understood the var keyword incorrectly. It's not any type until it's set. It's still statically typed.
It means: the compiler will figure out the type of the expression on the right-hand side of the assignement, and this will be the statically declared type of the variable.
Since DBQuery.FindString is declared as returning string (null or not), the declaration is 100% equivalent to:
string c = DBQuery.FindString("parameter", "data");
What you want to do is not possible in C#. You can declare the variable as object or dynamic and the code would work, but if you do so, you loose all design-time help such as IntelliSense (plus a runtime performance hit due to casting or dynamic typing).
In this question I saw an anonymous type expression with an unfamiliar syntax:
new { MyObjectID = g.Key, totalSum }
At first I thought it (, totalSum }) was a syntax error as no key is specified, but it compiles and works in C#3.0. I have verified this syntax in LINQPad (2.x -> C#3):
var y = ":-)";
var q = new { Y = y, y, y.Length, };
q.Dump();
Result:
(anon type) {
Y = ":-)",
y = ":-)",
Length = 3
}
Where in the specification is this syntax defined? (Answers should include an applicable reference and appropriate excerpt.)
And, more subjective (feel free not to answer), is it a good syntax/short-cut to omit the keys? I have not used it so far as I have not known about it, and I am not very enamored with that syntactical sugar.
7.6.10.6 Anonymous object creation expressions
A member declarator can be abbreviated
to a simple name (§7.5.2), a member
access (§7.5.4) or a base access
(§7.6.8). This is called a projection
initializer and is shorthand for a
declaration of and assignment to a
property with the same name.
Specifically, member declarators of
the forms
identifier expr . identifier
are precisely equivalent to
the following, respectively:
identifer = identifier identifier = expr . identifier
Thus, in a projection
initializer the identifier selects
both the value and the field or
property to which the value is
assigned. Intuitively, a projection
initializer projects not just a value,
but also the name of the value.
(page 181)
In simple terms this says that if you don't provide an identifier yourself, the compiler will select the identifier for the "last" member of the expression as a default.
As for if it's good or bad... well, I 'd avoid doing it precisely to rule out the possibility that someone else who doesn't know this shortcut is confused.
Not sure about C#-3.0, but the C#-4.0 reference talks about this in section 7.6.10.6 Anonymous object creation expressions.
An anonymous object initializer declares an anonymous type and returns an instance of that type. An anonymous type is a nameless class type that inherits directly from object. The members of an anonymous type are a sequence of read-only properties inferred from the anonymous object initializer used to create an instance of the type.
I've seen anonymous types used extensively in ASP.Net MVC for things like passing arbitrary HTML attributes to an Html Helper method.
In "CLR via C#" book it's mentioned that dynamic keyword corresponding FCL type is System.Object. please clarify this .
It's not the same thing from the C#'s point of view at all... but in the compiled code, a variable declared as type dynamic will usually (possibly always) correspond with a CLR field or local variable of type object.
The C# compiler is responsible for making sure that any source code using that value has the dynamic behaviour applied to it. object is simply the compiler the representation uses for storage. It also applies the [Dynamic] attribute where appropriate, so that other code knows it's to be treated dynamically.
For example, consider this:
public class Foo
{
public dynamic someField;
}
I believe that will be compiled into IL equivalent to:
public class Foo
{
[Dynamic]
public object someField;
}
now if you write:
Foo foo = new Foo();
foo.someField = "hello";
Console.WriteLine(foo.someField.Length);
the compiler uses the attribute to know that foo.someField is dynamic, so the Length property should be dynamically bound.
From MSDN:
The type is a static type, but an object of type dynamic bypasses static type checking. In most cases, it functions like it has type object.
And:
Type dynamic behaves like type object in most circumstances. However, operations that contain expressions of type dynamic are not resolved or type checked by the compiler. The compiler packages together information about the operation, and that information is later used to evaluate the operation at run time. As part of the process, variables of type dynamic are compiled into variables of type object. Therefore, type dynamic exists only at compile time, not at run time.
(emphasis mine)
Since a dynamic reference needs to be able to take any type, it is in effect of the type object (or at least to all appearances and uses), but the compiler will not perform certain type checks on it.
A colleague pointed me to a strange case in C# (not so sure if this actually strange though).
Suppose you have a class Employee. If you want to create a Generic List<> of type Employee, you can simply do:
List<Employee> x = new List<Employee>;
I understand that I need to pass the Employee type to the Generic list so that it knows the required type information about Employee and generates methods that return and accept parameters that are compatible with Employee.
Now my question is, why isn't it possible to do the following?
Employee x = new Employee();
List<typeof(x)> list = new List<typeof(x)>();
Shouldn't this suffice the information required for List<> to know, in order to create a list? In other words, the type of x which is the type of Employee is now passed as a generic type parameter to List<>, which (as I used to believe) is the same as passing list the type name (in this case Employee).
I know that something like this is available in Java (using the .class) keyword on a variable.
I'm sure I AM missing something, so please, enlight me guys!
No, the equivalent of that isn't available in Java. You can't use "x.class" to get at the declared type of a variable.
Moreover, typeof(x) doesn't work in C# either to get the type of a variable - it returns a Type reference for the type name, e.g. typeof(string) will return a reference to the Type object associated with the System.String type. That's equivalent to using String.class in Java. (Note that again, that's applying .class to a type name, not a variable name.)
Java generics don't support anything like your final statement either. If you believe they do, please give a sample :)
What you can do in C# is use type inference to do what you want:
public static List<T> CreateListForSampleType<T>(T sample)
{
return new List<T>();
}
...
Employee x = new Employee();
var list = CreateListForSampleType(x);
Note that there's no reason why C# couldn't be extended to allow something like typeof(variablename) or List<typeof(variablename)> - it's all compile-time type information, after all. However, I can't see that it would meet the team's requirements for usefulness... there are other far more useful features I'd like to see first :)
The reason for this is that typeof() returns a type object, while you need a type name to initialize a list at compile-time.
One part of the answer is that the type of x is not available at compile time, i.e. it might be created using something like this:
Employee x = EmployeeFactory.NewEmployee("John Doe"); // Returns TraineeEmployee, Employee or ManagementEmployee;
List<typeof(x)> l = new List<typeof(x)> l(); // What type is it?
You can however create a List of a base class of what you want to store in the list (or even a List of "object"s).
typeof is used with class names. Use GetType() on an object, but only at runtime...
What you are missing - imho - is the difference between a static type reference at compile-time and a dinamyc type reference (via an instance of System.Type) at run-time.
typeof() and .GetType() give you the latter. (for types and instances, respectively)
I hope it makes clear.
Jon Skeet's code above is cool.
Can't find a reason to create an empty list since C# 3.0.
I generally create list instances only with a ToList method from an IEnumerable, which is in turn generated using a yield return, Concat(), Repeat(), Where() etc.
var list = CreateEmployees().ToList();
,
public IEnumerable<Employee> CreateEmployees()
{
yield return new Employee("Foo");
yield return new Employee("Bar");
}
How good is C# type inference? I read somewhere that it's only for local variables? Does it work for class level attributes? For method signatures? Method return types? etc.
There are a few main kinds of type inference in C#:
Implicitly typed local variables:
Only for local variables
Only when the value is assigned as part of the declaration
Value cannot be null
Value cannot be a lambda expression, anonymous method or method group (without a cast)
The compile-time type of the value is used for the type of the variable
Any further uses of the variable are only checked against the type determined by the initial declaration+assignment; they don't contribute to the inference itself.
Generic method type argument inference, i.e. you don't specify the type arguments in a call to a generic method, the compiler figures them out based on the arguments.
Would be really handy to have this for generic types as well as generic methods
Really handy anyway - LINQ would be hard or impossible to use without it
Anonymous types would be fairly useless without it
Really complicated rules, even the spec is wrong in a few places
Lambda expression parameter type inference
Compiler tries to work out the types of the parameters for lambda expressions based on the context in which it's used
Usually works pretty well, in my experience
Array type inference, e.g. new[] { "Hi", "there" } instead of new string[] { "Hi", "there" }
Various small restrictions, nothing major
I've probably forgotten some other features which might be called "type inference". I suspect you're mostly interested in the first, but the others might be relevant to you too :)
It can only be used for local variables, but it can detect the type in many different forms.
var myVar = SomeMethodThatReturnsInt(); //will know it's an int
var myIntList = new List<int>(); //this works too (although this is technically not type inference)
var myOwnVar = new { Name = "John", Age = 100 }; // will create own type and infer that
EDIT: One more example of Tye Inference is with Lambdas. IE:
var myList = new List<int>();
//add some values to list
int x = myList.Find(i => i == 5); // compiler can infer that i is an int.
It works only with local variables as I understand it.