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.
Related
This question already has answers here:
Use of var keyword in C#
(86 answers)
Closed 8 years ago.
I usually create a object like these:
List<Student> students= new List<Student>();
but when I install the resharper in vs2012,it suggest me to create a object like these:
var students= new List<Student>();
I wonder whether they have the same effect.I think they have the same effect.Will it be better when I use var?
As suggested by Brad Smith http://www.brad-smith.info/blog/archives/336 :-
There seems to be a tendency for some programmers to use var for every
variable declaration. Sure, the language doesn’t stop you from doing
this and, indeed, MSDN admits that this is a “syntactic convenience”…
But it also warns quite strongly that:
the use of var does have at least the potential to make your code
more difficult to understand for other developers. For that reason,
the C# documentation generally uses var only when it is required.
Implicitly Typed Local Variables (C# Programming Guide), MSDN
I discovered recently that the commonly-used tool ReSharper
practically mandates liberal use of var. Frankly, this isn’t helping
the situation. There are some developers who try to argue the stance
that var somehow improves readability and broader coding practices,
such as this article:
By using var, you are forcing yourself to think more about how you
name methods and variables, instead of relying on the type system to
improve readability, something that is more an implementation detail…
var improves readability, Hadi Hariri
I agree with the premise of the quote above, but not with the end
result. On the contrary, the overuse and misuse of var can lead to
some very bad habits…
Let’s look at the argument against the widespread use of var (and for
its sparing, correct use):
Implicitly-typed variables lose descriptiveness
The type name provides an extra layer of description in a local
variable declaration:
// let's say we have a static method called GetContacts()
// that returns System.Data.DataTable
var individuals = GetContacts(ContactTypes.Individuals);
// how is it clear to the reader that I can do this?
return individuals.Compute("MAX(Age)", String.Empty);
My variable name above is perfectly descriptive; it differentiates
between any other variables populated using GetContacts() and indeed
other variables of type DataTable. When I operate on the variable, I
know that it’s the individual contacts that i’m referring to, and that
anything I derive from them will be of that context. However, without
specifying the type name in the declaration, I lose the
descriptiveness it provides…
// a more descriptive declaration
DataTable individuals = GetContacts(ContactTypes.Individuals)
When I come to revisit this body of code, i’ll know not only what the
variable represents conceptually, but also its representation in terms
of structure and usage; something lacking from the previous example.
No difference, by typing var instead of the data type that you are using, you just make the compiler look and set the data type himself. It makes the code a little shorter but in my opinion its better to write the data types full name instead of var.
It is same. But, the only difference is that, compiler determines the type of the variable.
How C# compiler does know the type of the variable?
The C# compiler infers the type of the variable from the
right-hand-side expression. For example, the type for the students is inferred from the type of the right-hand-side expression new List<Student>(), which makes students a type of
List<Student>().
var is just a syntactic sugar. It aliases any type. In your case, there is no difference between them. They both produce same Intermediate Language code.
Using var is just saying: "Hey compiler, just determine the type of this variable"
var just infers the type. You can use it in declarations like this when the resulting type is pretty obvious - it makes the code easier to read but doesn't make a difference to the compiler.
See also:
What is the significance of “var” keyword in c#.Net?
var (C# Reference)
I've been working in C for the past couple of years and I've managed to get use to putting single-purpose, static variables near where they are used within my code.
While writing a very basic method that was in need of a method-scope static value, I was a bit surprised to find that the compiler didn't like that I tried to define a static object from within my method.
Googling has verified that this isn't possible within C#. Still, I'm curious why code, like the following, is completely off limits.
public int incrementCounterAndReturn()
{
static int i = 0;
return ++i;
}
Granted, this is a simplistic example that could be redefined for the same affect but that's beside the point. Method-scope, static values have their place and purpose. What design decisions have prevented such an implementation of static objects within C#?
We're on C# version 5.0 and it's 2013. I can only assume this isn't possible because of a design choice and not just because "that's complex and hard stuff to implement." Does anyone have any insider information?
The language design team is not required to provide a reason to not implement a feature. Rather, the person who wants the feature is required to make the case that the feature is the best possible way the design, implementation, test, and education teams can be spending their budgets. No one has ever successfully done so for your proposed feature.
Were I still on the design team and had this feature pitched I would point out that it is completely unnecessary. The feature in C is a known cause of developer confusion, particularly for novices, and the benefit of local vs type scope is tiny.
The underlying runtime does not provide method level static variables. In the CLR, all "static" data is defined on the type level, not method level. C# decided to not add this at the language level in its language design.
This is purely a design choice. VB.Net, which compiles to the same IL, does allow this via the Shared keyword in a Function or Sub statement (though it's handled via the compiler "promoting" the variable to a class level static variable).
Because in the CLR, static variables are associated with the TYPE. Storage for them is tied to the Type (class or stuct) they are associated with.
static variables are scoped to the class, not to an object instance. To make this work, your method must be declared static, and I believe your class must also be static (since instantiation is not relevant).
But the variable itself must be declared at the class level. C# doesn't allow you to create method-local static variables.
Worth noting: these kinds of maneuvers make it very difficult to unit test the method properly. Normally in C# one would make an ordinary class to hold such state; in fact, that's exactly how yield return works behind the scenes.
The .NET framework and languages were designed around the concept that anyone who is going to be compiling an assembly should be considered trustworthy enough to have access to all the code therein. From a semantic point of view, declaring a static variable foo within method bar would be equivalent to declaring a private static variable outside the method and accessing it within the method, provided only that one chooses as a name something which isn't used anywhere else. If one by convention combines the method name and meaning (e.g. bar_foo) one can generally avoid naming collisions pretty easily. Since the semantics are equivalent to having the variable declared outside the method, there's no need to have it declared inside.
As discovered in C 3.5, the following would not be possible due to type erasure: -
int foo<T>(T bar)
{
return bar.Length; // will not compile unless I do something like where T : string
}
foo("baz");
I believe the reason this doesn't work is in C# and java, is due to a concept called type erasure, see http://en.wikipedia.org/wiki/Type_erasure.
Having read about the dynamic keyword, I wrote the following: -
int foo<T>(T bar)
{
dynamic test = bar;
return test.Length;
}
foo("baz"); // will compile and return 3
So, as far as I understand, dynamic will bypass compile time checking but if the type has been erased, surely it would still be unable to resolve the symbol unless it goes deeper and uses some kind of reflection?
Is using the dynamic keyword in this way bad practice and does this make generics a little more powerful?
dynamics and generics are 2 completely different notions. If you want compile-time safety and speed use strong typing (generics or just standard OOP techniques such as inheritance or composition). If you do not know the type at compile time you could use dynamics but they will be slower because they are using runtime invocation and less safe because if the type doesn't implement the method you are attempting to invoke you will get a runtime error.
The 2 notions are not interchangeable and depending on your specific requirements you could use one or the other.
Of course having the following generic constraint is completely useless because string is a sealed type and cannot be used as a generic constraint:
int foo<T>(T bar) where T : string
{
return bar.Length;
}
you'd rather have this:
int foo(string bar)
{
return bar.Length;
}
I believe the reason this doesn't work is in C# and java, is due to a concept called type erasure, see http://en.wikipedia.org/wiki/Type_erasure.
No, this isn't because of type erasure. Anyway there is no type erasure in C# (unlike Java): a distinct type is constructed by the runtime for each different set of type arguments, there is no loss of information.
The reason why it doesn't work is that the compiler knows nothing about T, so it can only assume that T inherits from object, so only the members of object are available. You can, however, provide more information to the compiler by adding a constraint on T. For instance, if you have an interface IBar with a Length property, you can add a constraint like this:
int foo<T>(T bar) where T : IBar
{
return bar.Length;
}
But if you want to be able to pass either an array or a string, it won't work, because the Length property isn't declared in any interface implemented by both String and Array...
No, C# does not have type erasure - only Java has.
But if you specify only T, without any constraint, you can not use obj.Lenght because T can virtually be anything.
foo(new Bar());
The above would resolve to an Bar-Class and thus the Lenght Property might not be avaiable.
You can only use Methods on T when you ensure that T this methods also really has. (This is done with the where Constraints.)
With the dynamics, you loose compile time checking and I suggest that you do not use them for hacking around generics.
In this case you would not benefit from dynamics in any way. You just delay the error, as an exception is thrown in case the dynamic object does not contain a Length property. In case of accessing the Length property in a generic method I can't see any reason for not constraining it to types who definately have this property.
"Dynamics are a powerful new tool that make interop with dynamic languages as well as COM easier, and can be used to replace much turgid reflective code. They can be used to tell the compiler to execute operations on an object, the checking of which is deferred to runtime.
The great danger lies in the use of dynamic objects in inappropriate contexts, such as in statically typed systems, or worse, in place of an interface/base class in a properly typed system."
Qouted From Article
Thought I'd weigh-in on this one, because no one clarified how generics work "under the hood". That notion of T being an object is mentioned above, and is quite clear. What is not talked about, is that when we compile C# or VB or any other supported language, - at the Intermediate Language (IL) level (what we compile to) which is more akin to an assembly language or equivalent of Java Byte codes, - at this level, there is no generics! So the new question is how do you support generics in IL? For each type that accesses the generic, a non-generic version of the code is generated which substitutes the generic(s) such as the ubiquitous T to the actual type it was called with. So if you only have one type of generic, such as List<>, then that's what the IL will contain. But if you use many implementation of a generic, then many specific implementations are created, and calls to the original code substituted with the calls to the specific non-generic version. To be clear, a MyList used as: new MyList(), will be substituted in IL with something like MyList_string().
That's my (limited) understanding of what's going on. The point being, the benefit of this approach is that the heavy lifting is done at compile-time, and at runtime there's no degradation to performance - which is again, why generic are probably so loved used anywhere, and everywhere by .NET developers.
On the down-side? If a method or type is used many times, then the output assembly (EXE or DLL) will get larger and larger, dependent of the number of different implementation of the same code. Given the average size of DLLs output - I doubt you'll ever consider generics to be a problem.
I am learning C# and .NET, and I frequently use the keyword var in my code. I got the idea from Eric Lippert and I like how it increases my code's maintainability.
I am wondering, though... much has been written in blogs about slow heap-located refs, yet I am not observing this myself. Is this actually slow? I am referring to slow compile times due to type inferencing.
You state:
I am referring to slow time for compile due to type 'inferencing'
This does not slow down the compiler. The compiler already has to know the result type of the expression, in order to check compatibility (direct or indirect) of the assignment. In some ways using this already-known type removes a few things (the potential to have to check for inheritance, interfaces and conversion operators, for example).
It also doesn't slow down the runtime; they are fully static compiled like regular c# variables (which they are).
In short... it doesn't.
'var' in C# is not a VARIANT like you're used to in VB. var is simply syntactic sugar the compiler lets you use to shorthand the type. The compiler figures out the type of the right-hand side of the expression and sets your variable to that type. It has no performance impact at all - just the same as if you'd typed the full type expression:
var x = new X();
exactly the same as
X x = new X();
This seems like a trivial example, and it is. This really shines when the expression is much more complex or even 'unexpressable' (like anonymous types) and enumerables.
Var is replaced at compile time with your actual variable type. Are you thinking of dynamic?
A "variant" is typeless, so access to state (or internal state conversion) always must go through two steps: (1) Determine the "real" internal type, and (2) Extract the relevant state from that "real" internal type.
You do not have that two-step process when you start with a typed object.
True, a "variant" thus has this additional overhead. The appropriate use is in those cases where you want the convenience of any-type for code simplicity, like is done with most scripting languages, or very high-level APIs. In those cases, the "variant" overhead is often not significant (since you are working at a high-level API anyway).
If you're talking about "var", though, then that is merely a convenience way for you to say, "Compiler, put the proper type here" because you don't want to do that work, and the compiler should be able to figure it out. In that case, "var" doesn't represent a (runtime) "variant", but rather a mere source-code specification syntax.
The compiler infers from the constructor the type.
var myString = "123"; is no different from string myString = "123";
Also, generally speaking, reference types live on the heap and value types live on the stack, regardless if they're declared using var.
So in C++, I'm used to being able to do:
typedef int PeerId;
This allows me to make a type more self-documenting, but additionally also allows me to make PeerId represent a different type at any time without changing all of the code. I could even turn PeerId into a class if I wanted. This kind of extensibility is what I want to have in C#, however I am having trouble figuring out how to create an alias for 'int' in C#.
I think I can use the using statement, but it only has scope in the current file I believe, so that won't work (The alias needs to be accessible between multiple files without being redefined). I also can't derive a class from built-in types (but normally this is what I would do to alias ref-types, such as List or Dictionary). I'm not sure what I can do. Any ideas?
You need to use the full type name like this:
using DWORD = System.Int32;
You could (ab)use implicit conversions:
struct PeerId
{
private int peer;
public static implicit operator PeerId(int i)
{
return new PeerId {peer=i};
}
public static implicit operator int(PeerId p)
{
return p.peer;
}
}
This takes the same space as an int, and you can do:
PeerId p = 3;
int i = p;
But I agree you probably don't need this.
Summary
Here's the short answer:
Typedefs are actually a variable used by compile-time code generators.
C# is being designed to avoid adding code generation language constructs.
Therefore, the concept of typedefs doesn't fit in well with the C# language.
Long Answer
In C++, it makes more sense: C++ started off as a precompiler that spit out C code, which was then compiled. This "code generator" beginning still has effects in modern C++ features (i.e., templates are essentially a Turing-complete language for generating classes and functions at compile time). In this context, a typedef makes sense because it's a way to get the "result" of a compile-time type factory or "algorithm" that "returns" a type.
In this strange meta-language (which few outside of Boost have mastered), a typedef is actually a variable.
What you're describing is less complex, but you're still trying to use the typedef as a variable. In this case, it's used as an input variable. So when other code uses the typedef, it's really not using that type directly. Rather, it's acting as a compile-time code generator, building classes and methods based on typedef'ed input variables. Even if you ignore C++ templates and just look at C typedefs, the effect is the same.
C++ and Generative Programming
C++ was designed to be a multi-paradign language (OO and procedural, but not functional until Boost came out). Interestingly enough, templates have evolved an unexpected paradign: generative programming. (Generative programming was around before C++, but C++ made it popular). Generative programs are actually meta-programs that - when compiled - generate the needed classes and methods, which are in turn compiled into executables.
C# and Generative Programming
Our tools are slowly evolving in the same direction. Of course, reflection emit can be used for "manual" generative programming, but it is quite painful. The way LINQ providers use expression trees is very generative in nature. T4 templates get really close but still fall short. The "compiler as a service" which will hopefully be part of C# vNext appears most promising of all, if it could be combined with some kind of type variable (such as a typedef).
This one piece of the puzzle is still missing: generative programs need some sort of automatic trigger mechanism (in C++, this is handled by implicit template instantiation).
However, it is explicitly not a goal of C# to have any kind of "code generator" in the C# language like C++ templates (probably for the sake of understandability; very few C++ programmers understand C++ templates). This will probably be a niche satisfied by T4 rather than C#.
Conclusion (repeating the Summary)
All of the above is to say this:
Typedefs are a variable used by code generators.
C# is being designed to avoid adding code generation language constructs.
Therefore, the concept of typedefs doesn't fit in well with the C# language.
I also sometimes feel I need (integer) typedefs for similar purposes to the OP.
If you do not mind the casts being explicit (I actually want them to be) you can do this:
enum PeerId : int {};
Will also work for byte, sbyte, short, ushort, uint, long, or ulong (obviously).
Not exactly the intended usage of enum, but it does work.
Since C# 10 you can use global using:
global using PeerId = System.Int32;
It works for all files.
It should appear before all using directives without the global modifier.
See using directive.
Redefining fundamental types just for the sake of changing the name is C++ think and does not sit well with the more pure Object Orientated C#. Whenever you get the urge to shoehorn a concept from one language into another, you must stop and think whether or not it makes sense and try to stay native to the platform.
The requirement of being able to change the underlying type easily can be satisfied by defining your own value type. Coupled with implicit conversion operators and arithmetic operators, you have the power to define very powerful types. If you are worried about performance for adding layers on top of simple types, don't. 99% chance that it won't, and the 1% chance is that in case it does, it will not the be "low hanging fruit" of performance optimization.