📜 ⬆️ ⬇️

Implicitly typed fields in C #

Today, another very interesting question was asked on QW : why in C # there are implicitly typed local variables aka var , but there are no implicitly typed fields?

In fact, this state of affairs is not at all accidental; so let's look at a few reasons why the compiler behaves this way and not otherwise.

First, the ability to use var , to declare implicitly typed local variables, has never been a stand-alone feature. When developing the C # language, no one set a goal to create a completely implicitly typed programming language, such as F #; implicit typing was only one component (albeit not the least important) of a more general concept, known today under the abbreviation LINQ.

Since during the development of LINQ, it was decided that tying a developer only to existing types is too “evil” a limitation, when it was implemented, the developer was given the opportunity to return sequences of anonymous classes. And if so, then without the use of implicitly typed variables this would not be possible:
')
IEnumerable <Customer> customers = null ;
// , result ? IEnumerable<??>?
var result = from c in customers
where c.Age > 33
select new {c.Name, c.Age};

* This source code was highlighted with Source Code Highlighter .


However, using the var keyword in a type declaration would in no way help to solve a more global goal (I’m talking about LINQ again).

Secondly, even if one does not climb too deeply into how difficult it would be for compiler writers (*) to realize such an opportunity, even without thinking, there are some drawbacks to its implementation and use. The first drawback is due to the fact that implicitly typed fields will be bad friends with anonymous types.

Let's imagine the following class:

public class Foo
{
public var someField = new {Name = "name" , Value = 12};
}

* This source code was highlighted with Source Code Highlighter .


Since anonymous types in .Net are now implemented as internal-types, it is simply impossible to “export” this type outside the current assembly. You can, of course, limit the use of implicitly typed fields only for internals of classes or private fields, or generally prohibit the use of implicitly typed fields with anonymous classes, but this will make the behavior of two semantically similar constructions of C # language too different. One of the reasons for the appearance of var in C # 3.0 is the use of anonymous types (with or without LINQ), and here it turns out that non-typed fields will not work with them.

Another important limitation is that implicitly typed fields introduce too close a connection between the field being initialized and the “initializer”. Let's look at an example: suppose we have a class A , which contains a “var” field called foo , which is initialized by calling the static method Foo of class B :

public class A
{
public static var foo = B.Foo();
}

public class B
{
public static int Foo()
{
return default ( int );
}
}

* This source code was highlighted with Source Code Highlighter .


This leads to a number of additional questions: what happens if classes A and B are located in different assemblies? But what if, without recompiling assembly A, an assembly with class B is recompiled and the return type of the Foo method changes from int to string ? Or else we may have an implicitly typed C. foo field (i.e., a foo field in class C ) tied to a field type A. foo , a D. foo field tied to a C. foo field, etc. and then changing the type of return value of one function will lead to a change in the field types in a dozen different classes (**). And in general, fields are a more important part of class design and its implementation in comparison with local variables, so changing on the fly the type of this field, just because someone changed the function signature in the third module is not a good idea.

Of course, it would be possible to limit the use of implicitly typed fields only in a limited set of cases, and prohibit the use of this feature with anonymous types and classes from other assemblies, and leave, for example, only using the methods of the current class. But even in this case, the implementation of this feature requires too much effort to implement (proof from Eric, I'm not here and J), which makes it rather low priority in the endless list of improvements that are in the heads of the developers of the C # compiler.

----------------------

(*) There is no point getting “in the jungle”, as Eric Lippert already did in his note Why no var on fields? in which he just says that the implementation of implicitly typed fields would require much more substantial implementation costs than the implementation of implicitly typed local variables.

(**) Of course, this is not an indicator, and any opportunity to use correctly or not correctly. But with the help of this thing you can pile up such that the example given in the note How not to write case code can also seem like flowers (since small changes will lead to mass not in one class, but also in a dozen others).

Source: https://habr.com/ru/post/127096/


All Articles