Browse DevX
Sign up for e-mail newsletters from DevX


C#: Why Do We Need Another Language? : Page 2

New computer languages are rare and successful ones are rarer still, yet Microsoft decided to create a new language to go along with the .NET Developer Platform. Why weren't existing languages good enough?




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Building Components
The .NET Developer Platform (NDP) is inherently a component-based environment and since C# exists only to create programs for NDP, it's not surprising that it's component-oriented.

There is no generally accepted definition for what a component is but, from the C# perspective, components are self-contained entities that support object-oriented programming. From the runtime perspective, this means that I can package one or more components into a .NET assembly and deploy them as a self-contained unit. (See Sidebar: What Is an Assembly)

C# provides important capabilities that make creating and using components easy.
From the programmer's perspective, it means that everything that it takes to create a component is contained within a C# source file. C# provides important capabilities that make creating and using components easy.

Properties and Indexers
Nearly all components have a set of attributes that they support. A textbox exposes the text that's in the textbox and the font for the text. A filename exposes the directory and the file extension.

When writing a component, programmers have had two choices for how to implement these attributes. The easiest choice is to make the attribute a public field that the user can access directly. In C#, it would look like this:

public class FileInfo { public string filename; public string directory; public string extension; public FileInfo(string filename) { // break apart into directory, // short name, and extension } }

That's simple to code and simple to use, but it has a few problems: the biggest of which is that it is inefficient because the class doesn't know when (or if) the user will want the directory. Therefore, it has to do the parsing every time.

The property design pattern was invented to solve this problem. The public fields are replaced with get and set accessor functions:

public class FileInfo { public string getFilename() { return filename; } public void setFilename(string filenameNew) { filename = filenameNew; } public string getDirectory() { // parse directory out, and return it } public string getExtension() { // parse extension out, and return it } private string filename; public FileInfo(string filename) { this.filename = filename; } }

This code is much nicer for the implementer. Since the user calls a function to get the values, you can postpone the work to create a value until the user asks for it. You can also cause other actions to take place when the user sets a value, such as repainting a control when its label is updated.

Unfortunately, you've made things tougher for the user. In the original version, the user would write:

FileInfo info = new FileInfo(filename); string extension = info.extension;

While in the property version, the user must write:

FileInfo info = new FileInfo(filename); string extension = info.getExtension();

It's worse if you want to increment a value. The simple version:


Becomes this:

counter.SetValue(counter.GetValue() + 1);

This code is considerably tougher to read or write. Additionally, the fact that getFilename() and setFilename() are related may not be obvious in the documentation or when using IntelliSense-like features.

To keep the advantages of the property idiom and still allow the user to have a model that looks like fields, C# provides full language support for properties. Using properties, our class would be written as:

public class FileInfo { public string Filename { get { return filename; } set { filename = value; } } public string Directory { get { // parse directory out, and return it } } public string Extension { get { // parse extension out, and return it } } private string filename; public FileInfo(string filename) { this.filename = filename; } }

The user now gets an attribute that can be used like a field, and the class author can write the class in an efficient manner.

The use of attributes generates a couple of concerns. One is whether programmers will confuse properties with fields and not realize that they're calling a method that could have a side effect. This rarely causes any real problems in practice because most .NET components don't expose fields and only expose properties, so programmers are used to properties and understand that they're executing code when they get or set a value. With properties, there's no difference between the Text field of a textbox control and the actual text displayed on the control because the property code ensures they are always in sync.

A second concern is one of efficiency. Properties take simple and fast field accesses and replace them with function calls. Luckily, it's fairly easy for a JIT compiler to recognize simple properties and generate code that is the equivalent of using a public field so there's no loss of efficiency in using properties.

Properties allow a user to use something that looks like a field. It's also useful for some components to be treated as if they are arrays. For example, it might be reasonable to treat an Employees class as if it is an array of Employee objects. C# supports indexers to provide this functionality, which are like properties with an additional index parameter:

class Employees { Employee[] employees; public Employee this[int index] { get { return employees[index]; } set { employees[index] = value; } } // other stuff here... }

The user can now write code like:

Employee current = employees[i];

Indexers can be overloaded to support indexing on multiple types (int and string, for example), and can also be multi-dimensional.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date