Related
Currently, I'm reading C# 5.0 in a Nutshell and in the Type Basics (located at Chapter 2) subtopic the term symmetry of predefined types and custom types is introduced...
...why the author talks about symmetry between those types? What are the argument to say that types are symmetric?
This is the original paragraph:
A beautiful aspect of C# is that predefined types and custom types have few differences. The predefined int type serves as a blueprint for integers. It holds data -32 bits- and provides function members that use that data, such as ToString. Similarly, our custom UnitConverter type acts as a blueprint for unit conversions. It holds data -the ratio- and provides function members to use that data.
The meaning of the text is that all of the types in the language "behave like objects". For example, you can do this:
int i = 42;
Console.WriteLine(i.ToString()); // called a method on an int
as easily as you can do this:
DateTime d = DateTime.Now;
Console.WriteLine(d.ToString()); // called a method on a DateTime
That is, if you did not know the types of i and d you would not be able to deduce anything by just reading the code that calls .ToString().
Contrast this with a language like C++:
std::string s = "hello";
std::cout << s.length();
int i = 42;
// ...but you cannot invoke any method on i; "ints are special"
Here the fact that s.length() compiles tells us that s is not an int, or a pointer, or any other primitive type.
This uniformity does not buy you anything from a technical standpoint, but it is nevertheless a welcome feature -- especially if you are just learning the language.
I believe the author's point is that built-in types and custom types are both meant to serve similar purposes; hold data and provide mechanisms for using that data. I believe there is also a veiled reference in there that both built-in objects and custom objects inherit from System.Object, thus they share similar abilities (i.e. ToString()).
I do not necessarily agree with term 'symmetry', but that is my two cents on the topic.
There are languages where you can't create type that behave similarly to something that is built in like int. In C# one can create type with all properties of 'int' (which is synonym of System.Int32) - value type with +/-/=operation.
I.e. in JavaScript one can't create another Array type or string type. In Java value types are (were?) not present, so type equivalent to 'int' can't be written by programmer ( Does Java make distinction between value type and reference type ).
I am reading the latest edition of this book for C# 10 and had the same question. I like all of the answers so far provided, but have one additional point: this is a reference to the utility of C#'s unified type system, which the author mentions briefly in Chapter 1 under the section 'Object Orientation':
Unified type system
The fundamental building block in C# is an encapsulated unit of data and functions called a type. C# has a unified type system in which all types ultimately share a common base type. This means that all types, whether they represent business objects or are primitive types such as numbers, share the same basic functionality. For example, an instance of any type can be converted to a string by calling its ToString() method.
To distill the author's writing and the comments from others down into a few points:
The type system of C# is unified, in that all types inherit from the common System.Object type.
Logically, type components can be logically grouped into two components: data members and function members.
Practically, because types behave like objects (they all have some data and/or behavior); developers can expect a minimum set of functionality from all types when using C#, such as the ability to call .ToString(), among other things.
These three points seem to be what the author had in mind when he referred to the C# type system having a 'symmetric beauty'.
This is probably a very simple question but I have a confusion about the Type definition.
When you want to provide a definition of the term Type such as Int, String or... Immediately the word Template comes to mind, but its so close to the "Class" definition, now I want to know what is exactly the definition of The term Type.
Is it the same as class definition !? Type == class !?
If so, we know that there are other (reference)Types in c# that are not Class such as Interface and Delegate.
Is it correct to use Type and Class interchangeably?
Could you please give me a comprehensive definition about Type.
thanks in advance.
As others have noted, the C# specification does not formally define "type". The C# spec does not attempt to be either a formal mathematical description of the language semantics or a tutorial for beginner programmers; you are expected to know what words like "type" and "value" and so on mean before you start reading the specification.
There are many possible definitions of "type", at varying levels of precision. For example, the ECMAScript specification somewhat informally defines a type as "a set of values", but since ECMAScript only has nine possible types, it does not need to have a strict, well-founded definition.
Another answer says that a type consists of a set of values, a set of rules for operating on those values, and a name. This is a very common working definition of a type, but it runs into problems when you try to think about it more formally. What is the name of an anonymous type? Is double*[][] the name of the type "jagged two dimensional array of pointers to double"? Does that type even have a name? Are List<int> and List<System.Int32> two different names for the same type? Does any set of values form a type? Are types themselves values? What is the type of a type? And so on. It's a good working definition but it doesn't quite hold up under scrutiny.
As a compiler writer, the way I think about types in C# is as follows: a type is a classification that can be applied to an expression. An expression is classified as being of a particular type if a proof exists that shows how the expression may be legally classified as that type, according to the rules of C#.
For example, suppose we are attempting to work out the type of the expression "1 + 2.3". We begin by working out the type of the expression "1". The rules of C# give us that; an expression of that form is always classified as an int. We work out the type of the expression "2.3". Again, the rules of C# tell us that an expression of this form is classified as "double". What is the type of the whole expression? The rules of C# tell us that the sum of an "int" and a "double" is classified as a "double". So the type of this expression is "double".
That's what the compiler does when it performs type analysis: it constructs proofs that particular expressions can legally be classified in particular ways, or, if the program is erroneous, it tells you why it was unable to construct a proof.
But all a type is, at this level, is simply a classification. You can do the same thing with any domain. You say that in the domain of positive integers, certain numbers are classified as "odd" and certain numbers are classified as "even". Certain numbers are classified as "prime" and "composite". If you want to classify a number, say, "123", then you might write a proof that shows that "123" is classified as both "odd" and "composite".
You can make up any classification you want, and you know what you just did? You just made a type. You can classify numbers into "the sum of two primes" and "not the sum of two primes", and "greater than four" and "not greater than four". And then you can combine them together into types like "even integers that are greater than four and not the sum of two odd primes". It is easy to determine if any particular integer is a member of this type; so far all integers that we've tried have been determined to not be members of that type. It is at this time unknown whether that type has any members or not; just because you can come up with a type does not mean that you know the size of the type!
A type system can allow any possible classification scheme. We could write C# so that "odd" and "even" and "prime" and "composite" were subtypes of "int". We could write C# so that any property of integers that you can write down is a subtype of int! We do not do so because such type systems put an enormous burden upon the compiler; compilers that work with such type systems are very complicated, very slow, and can get into situations where they have to solve impossible problems. The designers of the CLR and C# built the type system that we have such that the compiler can (usually) be extremely fast in classifying expressions into types.
No, it's not correct to use "type" and "class" interchangably.
A type can be any of:
A class
An interface
A delegate type
An enum type
A struct
A pointer type
An array type (which is also a class)
As far as I can see, the C# spec doesn't really "define" the word "type". Even as early as the introduction it talks about C# having a "unified type system" without defining what a type is.
I suspect that for most developers, giving examples of what you mean by the word "type" is simpler and more communicative than trying to define the word accurately.
You shouldn't use type and class interchangeably.
This is an interesting read regarding types.
Note that types include structs, interfaces, delegates, pointer types and enum constructs as well as classes.
Here goes...
A type is anything that can be instantiated (my definition, not MSFT's).
An interface can be instantiated in the sense that there must be another type that implements the interface.
Anonymous types are types for which there is no class definition, but they can be instantiated.
Any type may inherit from another (non-anonymous) type. We then call that other type the base type.
EDIT: As Jon Skeet remarked, static classes cannot be instantiated, so my definition falls flat. Maybe it should be "anything that can be instantiated, OR a static class"...
The best workaday answer I can come up with is:
A type is a collection of values, a collection of operations on those values, and a name to make it unique.
If you are looking for a deep answer about what a type fundamentally is from a computer science perspective, I don't think you'll find it in the C# documentation. Types are something that most of us use successfully in our daily lives without having to pin down their exact definition. But if you really want to know I think you'll find better answers in the programming theory and languages community (specifically, ML and Haskell) where people take great care to precisely formalize what they are talking about.
The Wikipedia entry for Type System is a good place to start.
Classes and types are not interchangeble. A class is always a type, but a type is not always a class. Structs and interfaces, for example, are type, but not classes.
"type" is simply short for "data type". Any variable you use has some data type, be it a so called "simple type" (like int or long) or a "complex type" like a struct or a class.
While a class is always a type, not every type is a class. For example, int is a type but not a class. C# has the feature that for every simple type there's also a representing class (bool => Boolean).
You can not use class and type interchangeably, but it will mostly be understood if you do :-)
If I have various subclasses of something, and an algorithm which operates on instances of those subclasses, and if the behaviour of the algorithm varies slightly depending on what particular subclass an instance is, then the most usual object-oriented way to do this is using virtual methods.
For example if the subclasses are DOM nodes, and if the algorithm is to insert a child node, that algorithm differs depending on whether the parent node is a DOM element (which can have children) or DOM text (which can't): and so the insertChildren method may be virtual (or abstract) in the DomNode base class, and implemented differently in each of the DomElement and DomText subclasses.
Another possibility is give the instances a common property, whose value can be read: for example the algorithm might read the nodeType property of the DomNode base class; or for another example, you might have different types (subclasses) of network packet, which share a common packet header, and you can read the packet header to see what type of packet it is.
I haven't used run-time-type information much, including:
The is and as keywords in C#
Downcasting
The Object.GetType method in dot net
The typeid operator in C++
When I'm adding a new algorithm which depends on the type of subclass, I tend instead to add a new virtual method to the class hierarchy.
My question is, when is it appropriate to use run-time-type information, instead of virtual functions?
When there's no other way around. Virtual methods are always preferred but sometimes they just can't be used. There's couple of reasons why this could happen but most common one is that you don't have source code of classes you want to work with or you can't change them. This often happens when you work with legacy system or with closed source commercial library.
In .NET it might also happens that you have to load new assemblies on the fly, like plugins and you generally have no base classes but have to use something like duck typing.
In C++, among some other obscure cases (which mostly deal with inferior design choices), RTTI is a way to implement so-called multi methods.
This constructions ("is" and "as") are very familiar for Delphi developers since event handlers usually downcast objects to a common ancestor. For example event OnClick passes the only argurment Sender: TObject regardless of the type of the object, whether it is TButton, TListBox or any other. If you want to know something more about this object you have to access it through "as", but in order to avoid an exception, you can check it with "is" before. This downcasting allows design-type binding of objects and methods that could not be possible with strict class type checking. Imagine you want to do the same thing if the user clicks Button or ListBox, but if they provide us with different prototypes of functions, it could not be possible to bind them to the same procedure.
In more general case, an object can call a function that notifies that the object for example has changed. But in advance it leaves the destination the possibility to know him "personally" (through as and is), but not necessarily. It does this by passing self as a most common ancestor of all objects (TObject in Delphi case)
dynamic_cast<>, if I remember correctly, is depending on RTTI. Some obscure outer interfaces might also rely on RTTI when an object is passed through a void pointer (for whatever reason that might happen).
That being said, I haven't seen typeof() in the wild in 10 years of pro C++ maintenance work. (Luckily.)
You can refer to More Effective C# for a case where run-time type checking is OK.
Item 3. Specialize Generic Algorithms
Using Runtime Type Checking
You can easily reuse generics by
simply specifying new type parameters.
A new instantiation with new type
parameters means a new type having
similar functionality.
All this is great, because you write
less code. However, sometimes being
more generic means not taking
advantage of a more specific, but
clearly superior, algorithm. The C#
language rules take this into account.
All it takes is for you to recognize
that your algorithm can be more
efficient when the type parameters
have greater capabilities, and then to
write that specific code. Furthermore,
creating a second generic type that
specifies different constraints
doesn't always work. Generic
instantiations are based on the
compile-time type of an object, and
not the runtime type. If you fail to
take that into account, you can miss
possible efficiencies.
For example, suppose you write a class that provides a reverse-order enumeration on a sequence of items represented through IEnumerable<T>. In order to enumerate it backwards you may iterate it and copy items into an intermediate collection with indexer access like List<T> and than enumerate that collection using indexer access backwards. But if your original IEnumerable is IList why not take advantage of it and provide more performant way (without copying to intermediate collection) to iterate items backwards. So basically it is a special we can take advantage of but still providing the same behavior (iterating sequence backwards).
But in general you should carefully consider run-time type checking and ensure that it doesn't violate Liskov Substituion Principle.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
Are there philosophical differences between Smalltalk OOP and Simula OOP ?
This is a question related to Java & C# vs C++ indirectly. As I understand, C++ is based on Simula but Java and C# are more or less from the Smalltalk family.
Several key 'differences in 'Style' within the broader OOP banner.
In all cases a statement about a static or dynamic type system means predominately one or the other, the issue is far from clear cut or clearly defined.
Also many languages choose the blur the line between the choices so this is not a list of binary choices by any means.
Polymorphic late binding
or "what does foo.Bar(x) mean?"
Hierarchy of types is flattened to a specific implementation per instance (often done via a vtable) and often allowing explicit reference to the base classes implementation.
Conceptually you look at the most specific type that foo is at the callsite. If it has an implementation of Bar for the parameter x that is called, if not the parent of foo is chosen and the process repeated.
Examples: C++/Java/C#, "Simula style" is often used.
Pure message passing. The code in foo which handles messages 'named' "Bar" is asked to accept the x. Only the name matters, not any assumptions the call site may have had about exactly what Bar was meant to be. Contrast with the previous style in which the method in question was Bar known to be something defined on whatever was known about the type hierarchy defined at compile time (though the precise place in the hierarchy is left till runtime).
Examples: Objective-C/Ruby, "Smalltalk style" is often used.
1 is often used within statically typed frameworks where it is an error, checked at compile time for no such implementation to exist. Further the languages often differentiate between Bar(x) and Bar(y) if x and y are different types. This is method overloading and the resulting methods with the same name are viewed as entirely different.
2 is often used in dynamic languages (which tend to avoid method overloading) as such it is possible that, at runtime the type of foo has no 'handler' for the message named 'Bar', different languages handle this in different ways.
Both can be implemented behind the scenes in the same fashion if desired (often the default for the second, Smalltalk style is to invoke a function but this is not made a defined behaviour in all cases).
Since the former method can frequently be easily implemented as simple pointer offset function calls it can, more easily, be made relatively fast. This does not mean that the other styles cannot also be made fast, but more work may be required to ensure that the greater flexibility is not compromised when doing so.
Inheritance/Reuse
or "Where do babies come from?"
Class based
Method implementations are organized into groups called classes. When implementation inheritance is desired a class is defined which extends the parent class. In this way it gains all exposed aspects of the parent (both fields and methods) and can choose to alter certain/all of those aspects but cannot remove any. You can add and update but not delete.
Examples: C++/Java/C# (note both SmallTalk and Simula use this)
Prototype based
Any instance of an object is simply a collection of identified methods (normally identified by name) and state in the form of (again named) fields. Whenever a new instance of this 'type' is desired an existing instance can be used to clone a new one. This new class retains a copy of the state and methods of the previous class but can then be modified to remove, add or alter existing named fields and methods.
Examples: Self/JavaScript
Again 1 tends to happen in static languages, 2 in dynamic though this is by no means a requirement they simply lend themselves to the style.
Interface or Class based
or "what or how?"
Interfaces list the methods that are required. They are a contract
Examples: VB6
Classes list methods that are required but may optionally supply their implementation
Examples: Simula
This is very much not a binary choice. Most class based languages allow the concept of abstract methods (ones with no implementation yet). If you have a class where all methods are abstract (called pure virtual in C++) then what the class amounts to is pretty much an interface, albeit one that may have also defined some state (fields). An true Interface should have no state (since it defines only what is possible, not how it happens.
Only older OOP languages tend to rely solely on one or the other.
VB6 has only on interfaces and have no implementation inheritance.
Simula let you declare pure virtual classes but you could instantiate them (with runtime errors on use)
Single or Multiple Inheritance
or "Who is the daddy?"
Single
Only one type can be a parent to another. In the Class based form above you can extend (take implementation from) only one type. Typically this form includes the concept of interfaces as first class aspects of the language to make up for this.
advantages include cleaner metadata and introspection, simpler language rules.
complications include making it harder to bring useful methods into scope (things like MixIns and Extension methods seek to mitigate this sort of problem)
Examples: C#/java
Multiple - you can extend multiple classes
advantages include certain structures are easier to model and design
complications include complex rules for collision resolution, especially when overloaded methods exist which could take either parent type.
Examples: C++/Eiffel
This question provokes considerable debate, especially as it is a key differentiator between C++'s OOP implementation and many of the modern statically typed languages perceived as possible successors like c# and java.
Mutability
or "what do you want to do to me?"
Mutable
Objects, once created can have their state changed.
Imutable
Objects, once created cannot be changed.
Frequently this is not an all or nothing it is simply a default (most commonly used OOP languages default to mutable by default). This can have a great deal of affect on how the language is structured. Many primarily functional languages which have included OOP features default the objects to have immutable state.
'Pureness' of their OOP
or "Is everything an Object?"
Absolutely everything in the system is viewed as an object (possibly even down to the methods themselves which are simply another kind of object and can be interacted with in the same way other objects can be).
Examples: SmallTalk
Not everything is an object, you cannot pass messages to everything (though the system might jump through hoops to make it seem like you can)
Examples: C++/C#/Java (see note*)
This is quite complex since techniques like auto boxing of primitives make it seem like everything is but you will find that several boundary cases exist where this 'compiler magic' is discovered and the proverbial wizard of Oz is found behind the curtain resulting is problems or errors.
In languages with immutability as a default this is less likely to happen, since the key aspect of objects (that they contain both methods and state) means that things that are similar to objects but not quite have less possibility for complications.
In regards to Java/C# the autoboxing(or in c#) system lets you treat, syntactically any variable as if it was an object but, in actuality this is not the case and this is exhibited in areas such as attempting to lock on an autoboxed object (rejected by the compiler as it would be an obvious bug).
Static or Dynamic
or "Who do you think you are?"
A far more pervasive aspect of language design and not one to get into here but the choices inherent in this decision impact many aspects of OOP as mentioned earlier.
Just aspects of the polymorphic late binding can depend on:
The type of the object to whom the message is being passed (at compile time/run time)
The type of the parameter(s) which are being passed (at compile time/run time)
The more dynamic a language gets the more complex these decisions tend to become but conversely the more input the language user, rather than the language designer has in the decision.
Giving examples here would be some what foolhardy since statically typed languages may be modified to include dynamic aspects (like c# 4.0).
I'd put Java and C# in the Simula camp as well:
Smalltalk, being dynamically typed, is quite apart of the four other languages you cite.
Smalltalk is structurally typed (alias duck typing) while the other four are nominally typed.
(What Java and C# have in common with Smalltalk is being mainly based on a VM, but there is little influence on the programming style).
Java and C# are definitely not from the Smalltalk family. Alan Kay even said that when he created OOP he did not have anything like Java or C++ in mind. Java, C#, and C++ all interpret OOP in pretty much the same way.
Languages like Smalltalk and Ruby have a radically different model that is based on message passing. In C++ classes are essentially namespaces for methods and state. Method invocations are bound at compile time. Smalltalk does not bind a "method call" until runtime. The result of this is that in C++
foo->bar
is compiled to mean "call the bar method on the foo object." If bar is non virtual, I'd imagine that the address of the bar method is specifically referenced.
In Smalltalk
foo bar
means "send the message bar to the foo object." foo can do whatever it wants with this message when it arrives. The default behavior is to call the method named bar, but that is not required. This property is exploited in Ruby for ActiveRecord column accessors. When you have an ActiveRecord object and you send it the name of a column in its database table as a message, if there is no method with that name defined, it checks to see if there is a column by that name on the table and if there is returns the value.
Message passing might seem like a tiny, irrelevant detail, but out of it, the rest of OOP easily flows.
"OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. It can be done in Smalltalk and in LISP. There are possibly other systems in which this is possible, but I'm not aware of them." -- Alan Kay, creator of Smalltalk
Eiffel is a statically typed, compiled, multiple inheritance pure OOP language.
http://dev.eiffel.com
Of the modern (and I use the term lightly) OO programming languages Objective C is the most like smalltalk.
Messaages:
In C++,C# and Java: messages are bound at compile time.
You can think of a method call as a message being sent to the object.
In Objective C,Smalltalk: messages are bound at run time.
I would say statically typed and dynamically typed OOP are two separate disciplines within the same school of OOP.
Java, C#, and C++ all follow a similar OOP strategy. It is based on function calls that are bound at compile time. Depending ont he call, either the direct function call or an offset into a vtable is fixed when compilation happens. By contrast Smalltalk's OOP is based on message passing. Conceptually every method call is a message to the receiving object asking whether it has a method called "Foo."
Smalltalk has no concept of interfaces. It only has similar looking methods. In the C++ group of languages, everything is bound to interfaces. One cannot implement AddRef and Release without also implementing QueryInterface (even if it is just a stub) because they are all part of the IUnknown interface. In Smalltalk, there is no IUnknown. There is only a collection of 3 functions, any of which could be implemented or not.
I'd say there is also a pretty big difference, conceptually, between class-based OOP (of which Smalltalk, Simula, C# and Java are all examples) and prototype-based OOP (which started with Self and is most widespread in JavaScript).
Aside from the above points, there is also a conceptual breakdown of Smalltalk vs. Simula.
Conceptually, "Smalltalk-style" typically indicates that the method run when a message is called is determined at run time, aiding polymorphism.
"Simula-style", on the other hand, usually seems to indicate where all method calls are really just a convenient way of writing overloaded function calls--no runtime polymorphism. (Please correct me if I'm wrong.)
In the middle, we have Java: all methods virtual by default, but statically typed and has compile-time type dispatch.
Example:
// C++
class Base {
void doSomething() {
cout << "Base::doSomething() called!\n";
}
}
class Derived : Base {
void doSomething() {
cout << "Derived::doSomething() called!\n";
}
}
int main() {
Base* b = new Base();
Derived* d = new Derived();
b->doSomething(); // prints "Base::doSomething() called!"
d->doSomething(); // prints "Derived::doSomething() called!"
Base* d2 = d; // OK; Liskov substitution principle.
d2->doSomething(); // prints "Base::doSomething called!" (!)
delete b;
delete d;
return 0;
}
VS:
// Objective-C
//Base.h
#interface Base
{
}
-(void)doSomething
#end
//Base.m
#import "Base.h"
#implementation Base
-(void) doSomething {
printf("doSomething sent to Base!");
}
#end
//Derived.h
#import "Base.h"
#import "Base.m"
#interface Derived : Base
{
}
#end
//Derived.m
#import "Derived.h"
#implementation Derived
-(void) doSomething {
printf("doSomething sent to Derived!")
}
#end
//Main.m
#import "Base.h"
#import "Base.m"
#import "Derived.h"
#import "Derived.m"
int main() {
Base* b = [[Base alloc] init];
Derived* d = [[Derived alloc] init];
[b doSomething]; // prints "doSomething sent to Base!"
[d doSomething]; // prints "doSomething sent to Derived!"
Base* d2 = d;
[d2 doSomething]; // prints "doSomething sent to Derived!"
[b release];
[d release];
return 0;
}
I am a PHP web programmer who is trying to learn C#.
I would like to know why C# requires me to specify the data type when creating a variable.
Class classInstance = new Class();
Why do we need to know the data type before a class instance?
As others have said, C# is static/strongly-typed. But I take your question more to be "Why would you want C# to be static/strongly-typed like this? What advantages does this have over dynamic languages?"
With that in mind, there are lots of good reasons:
Stability Certain kinds of errors are now caught automatically by the compiler, before the code ever makes it anywhere close to production.
Readability/Maintainability You are now providing more information about how the code is supposed to work to future developers who read it. You add information that a specific variable is intended to hold a certain kind of value, and that helps programmers reason about what the purpose of that variable is.
This is probably why, for example, Microsoft's style guidelines recommended that VB6 programmers put a type prefix with variable names, but that VB.Net programmers do not.
Performance This is the weakest reason, but late-binding/duck typing can be slower. In the end, a variable refers to memory that is structured in some specific way. Without strong types, the program will have to do extra type verification or conversion behind the scenes at runtime as you use memory that is structured one way physically as if it were structured in another way logically.
I hesitate to include this point, because ultimately you often have to do those conversions in a strongly typed language as well. It's just that the strongly typed language leaves the exact timing and extent of the conversion to the programmer, and does no extra work unless it needs to be done. It also allows the programmer to force a more advantageous data type. But these really are attributes of the programmer, rather than the platform.
That would itself be a weak reason to omit the point, except that a good dynamic language will often make better choices than the programmer. This means a dynamic language can help many programmers write faster programs. Still, for good programmers, strongly-typed languages have the potential to be faster.
Better Dev Tools If your IDE knows what type a variable is expected to be, it can give you additional help about what kinds of things that variable can do. This is much harder for the IDE to do if it has to infer the type for you. And if you get more help with the minutia of an API from the IDE, then you as a developer will be able to get your head around a larger, richer API, and get there faster.
Or perhaps you were just wondering why you have to specify the class name twice for the same variable on the same line? The answer is two-fold:
Often you don't. In C# 3.0 and later you can use the var keyword instead of the type name in many cases. Variables created this way are still statically typed, but the type is now inferred for you by the compiler.
Thanks to inheritance and interfaces sometimes the type on the left-hand side doesn't match the type on the right hand side.
It's simply how the language was designed. C# is a C-style language and follows in the pattern of having types on the left.
In C# 3.0 and up you can kind of get around this in many cases with local type inference.
var variable = new SomeClass();
But at the same time you could also argue that you are still declaring a type on the LHS. Just that you want the compiler to pick it for you.
EDIT
Please read this in the context of the users original question
why do we need [class name] before a variable name?
I wanted to comment on several other answers in this thread. A lot of people are giving "C# is statically type" as an answer. While the statement is true (C# is statically typed), it is almost completely unrelated to the question. Static typing does not necessitate a type name being to the left of the variable name. Sure it can help but that is a language designer choice not a necessary feature of static typed languages.
These is easily provable by considering other statically typed languages such as F#. Types in F# appear on the right of a variable name and very often can be altogether ommitted. There are also several counter examples. PowerShell for instance is extremely dynamic and puts all of its type, if included, on the left.
One of the main reasons is that you can specify different types as long as the type on the left hand side of the assignment is a parent type of the type on the left (or an interface that is implemented on that type).
For example given the following types:
class Foo { }
class Bar : Foo { }
interface IBaz { }
class Baz : IBaz { }
C# allows you to do this:
Foo f = new Bar();
IBaz b = new Baz();
Yes, in most cases the compiler could infer the type of the variable from the assignment (like with the var keyword) but it doesn't for the reason I have shown above.
Edit: As a point of order - while C# is strongly-typed the important distinction (as far as this discussion is concerned) is that it is in fact also a statically-typed language. In other words the C# compiler does static type checking at compilation time.
C# is a statically-typed, strongly-typed language like C or C++. In these languages all variables must be declared to be of a specific type.
Ultimately because Anders Hejlsberg said so...
You need [class name] in front because there are many situations in which the first [class name] is different from the second, like:
IMyCoolInterface obj = new MyInterfaceImplementer();
MyBaseType obj2 = new MySubTypeOfBaseType();
etc. You can also use the word 'var' if you don't want to specify the type explicitely.
Why do we need to know the data type
before a class instance?
You don't! Read from right to left. You create the variable and then you store it in a type safe variable so you know what type that variable is for later use.
Consider the following snippet, it would be a nightmare to debug if you didn't receive the errors until runtime.
void FunctionCalledVeryUnfrequently()
{
ClassA a = new ClassA();
ClassB b = new ClassB();
ClassA a2 = new ClassB(); //COMPILER ERROR(thank god)
//100 lines of code
DoStuffWithA(a);
DoStuffWithA(b); //COMPILER ERROR(thank god)
DoStuffWithA(a2);
}
When you'r thinking you can replace the new Class() with a number or a string and the syntax will make much more sense. The following example might be a bit verbose but might help to understand why it's designed the way it is.
string s = "abc";
string s2 = new string(new char[]{'a', 'b', 'c'});
//Does exactly the same thing
DoStuffWithAString("abc");
DoStuffWithAString(new string(new char[]{'a', 'b', 'c'}));
//Does exactly the same thing
C#, as others have pointed out, is a strongly, statically-typed language.
By stating up front what the type you're intending to create is, you'll receive compile-time warnings when you try to assign an illegal value. By stating up front what type of parameters you accept in methods, you receive those same compile-time warnings when you accidentally pass nonsense into a method that isn't expecting it. It removes the overhead of some paranoia on your behalf.
Finally, and rather nicely, C# (and many other languages) doesn't have the same ridiculous, "convert anything to anything, even when it doesn't make sense" mentality that PHP does, which quite frankly can trip you up more times than it helps.
c# is a strongly-typed language, like c++ or java. Therefore it needs to know the type of the variable. you can fudge it a bit in c# 3.0 via the var keyword. That lets the compiler infer the type.
That's the difference between a strongly typed and weakly typed language. C# (and C, C++, Java, most more powerful languages) are strongly typed so you must declare the variable type.
When we define variables to hold data we have to specify the type of data that those variables will hold. The compiler then checks that what we are doing with the data makes sense to it, i.e. follows the rules. We can't for example store text in a number - the compiler will not allow it.
int a = "fred"; // Not allowed. Cannot implicitly convert 'string' to 'int'
The variable a is of type int, and assigning it the value "fred" which is a text string breaks the rules- the compiler is unable to do any kind of conversion of this string.
In C# 3.0, you can use the 'var' keyword - this uses static type inference to work out what the type of the variable is at compile time
var foo = new ClassName();
variable 'foo' will be of type 'ClassName' from then on.
One things that hasn't been mentioned is that C# is a CLS (Common Language Specification) compliant language. This is a set of rules that a .NET language has to adhere to in order to be interopable with other .NET languages.
So really C# is just keeping to these rules. To quote this MSDN article:
The CLS helps enhance and ensure
language interoperability by defining
a set of features that developers can
rely on to be available in a wide
variety of languages. The CLS also
establishes requirements for CLS
compliance; these help you determine
whether your managed code conforms to
the CLS and to what extent a given
tool supports the development of
managed code that uses CLS features.
If your component uses only CLS
features in the API that it exposes to
other code (including derived
classes), the component is guaranteed
to be accessible from any programming
language that supports the CLS.
Components that adhere to the CLS
rules and use only the features
included in the CLS are said to be
CLS-compliant components
Part of the CLS is the CTS the Common Type System.
If that's not enough acronyms for you then there's a tonne more in .NET such as CLI, ILasm/MSIL, CLR, BCL, FCL,
Because C# is a strongly typed language
Static typing also allows the compiler to make better optimizations, and skip certain steps. Take overloading for example, where you have multiple methods or operators with the same name differing only by their arguments. With a dynamic language, the runtime would need to grade each version in order to determine which is the best match. With a static language like this, the final code simply points directly to the appropriate overload.
Static typing also aids in code maintenance and refactoring. My favorite example being the Rename feature of many higher-end IDEs. Thanks to static typing, the IDE can find with certainty every occurrence of the identifier in your code, and leave unrelated identifiers with the same name intact.
I didn't notice if it were mentioned yet or not, but C# 4.0 introduces dynamic checking VIA the dynamic keyword. Though I'm sure you'd want to avoid it when it's not necessary.
Why C# requires me to specify the data type when creating a variable.
Why do we need to know the data type before a class instance?
I think one thing that most answers haven't referenced is the fact that C# was originally meant and designed as "managed", "safe" language among other things and a lot of those goals are arrived at via static / compile time verifiability. Knowing the variable datatype explicitly makes this problem MUCH easier to solve. Meaning that one can make several automated assessments (C# compiler, not JIT) about possible errors / undesirable behavior without ever allowing execution.
That verifiability as a side effect also gives you better readability, dev tools, stability etc. because if an automated algorithm can understand better what the code will do when it actually runs, so can you :)
Statically typed means that Compiler can perform some sort of checks at Compile time not at run time. Every variable is of particular or strong type in Static type. C# is strongly definitely strongly typed.