There are only 2 kinds of data types in .net framework:
- Value Type and
- Reference Type
A type which is allocated in the stack area of memory, meaning that when the scope of the variable is over, it's cleaned up.
What is a reference type:
When an object is allocated from the managed heap, the new operator returns the memory address of the object. You usually store this address in a variable. This is called a reference type variable because the variable does not actually contain the object's bits; instead, the variable refers to the object's bits.
Some Differences & Comparision B/w these 2 Types:
- Reference type variables contain the memory address of objects in the heap. By default, when a reference type variable is created, it is initialized to null, indicating that the reference type variable doesn't currently point to a valid object. Attempting to use a null reference type variable causes a NullReferenceException exception. By contrast, value type variables always contain a value of the underlying type. By default, all members of the value type are initialized to zero. It is not possible to generate a NullReferenceException exception when accessing a value type.
- There are some performance issues to consider when working with reference types. First, the memory must be allocated from the managed heap, which could force a garbage collection to occur. Second, reference types are always accessed via their pointers. So every time your code references any member of an object on the heap, code must be generated and executed to dereference the pointer in order to perform the desired action. This adversely affects both size and speed.
- When you assign a value type variable to another value type variable, a copy of the value is made. When you assign a reference type variable to another reference type variable, only the memory address is copied.
Because of the previous point, two or more reference type variables may refer to a single object in the heap. This allows operations on one variable to affect the object referenced by the other variable. On the other hand, value type variables each have their own copy of the object's data, and it is not possible for operations on one value type variable to affect another.value type is better in performance, because the variable contains the object directly and there is no need of a reference. When possible, you should use value types instead of reference types because your application's performance will be better. - When type is passed as a reference to the function both members of the type & the type itself can be changed, where as when passed as a value type only the the members of the type can be changed. It's not possible to change the type of reference object to a new address in a function with a value parameter where as in a function with a reference type parameter it's possible to change the members as well as to a new address for the current input.
- Reference parameters don't pass the values of the variables used in the function member invocation - they use the variables themselves. Rather than creating a new storage location for the variable in the function member declaration, the same storage location is used, so the value of the variable in the function member and the value of the reference parameter will always be the same.
Some examples to illustrate the above points:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ValueTypeRefTypeDiff { class Program { static void Main(string[] args) { Console.WriteLine("------ValueType Lessons------"); Product apple = new Product("Apple", 150); Console.WriteLine("Created a new product"); Console.WriteLine(string.Format("The product name:{0} , Rate:{1}", apple.ProductName, apple.Rate)); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Passing this product as value type to the function"); Console.WriteLine("Trying to change the properties of product..."); ValueTypeChangeProperties(apple); Console.WriteLine(string.Format("The product name:{0} , Rate:{1}", apple.ProductName, apple.Rate)); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Lesson1:"); Console.WriteLine("Properties of the product changed..."); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Passing this product as value type to the function"); Console.WriteLine("Trying to change the properties of product & then Product itself..."); ValueTypeChangePropertiesAndProductToo(apple); Console.WriteLine(string.Format("The product name:{0} , Rate:{1}", apple.ProductName, apple.Rate)); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Lesson2:"); Console.WriteLine("Only properties changed no change in product..."); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("------ReferenceType Lessons------"); Product objapple = new Product("Apple", 150); Console.WriteLine("Created a new product"); Console.WriteLine(string.Format("The product name:{0} , Rate:{1}", objapple.ProductName, objapple.Rate)); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Passing this product as reference type to the function"); Console.WriteLine("Trying to change the properties of product..."); ReferenceTypeChangeProperties(ref objapple); Console.WriteLine(string.Format("The product name:{0} , Rate:{1}", objapple.ProductName, objapple.Rate)); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Lesson1:"); Console.WriteLine("Properties of the product changed..."); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Passing this product as reference type to the function"); Console.WriteLine("Trying to change the properties of product & then Product itself..."); ReferenceTypeChangePropertiesAndProdcutToo(ref objapple); Console.WriteLine(string.Format("The product name:{0} , Rate:{1}", objapple.ProductName, objapple.Rate)); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Lesson2:"); Console.WriteLine("Both properties as well as product can be changed..."); Console.ReadLine(); } private static void ValueTypeChangeProperties(Product p) { p.Rate = 30; } private static void ValueTypeChangePropertiesAndProductToo(Product p) { p.Rate = 43; p = new Product("Orange",40); } private static void ReferenceTypeChangeProperties(ref Product p) { p.Rate = 20; } private static void ReferenceTypeChangePropertiesAndProdcutToo(ref Product p) { p.Rate = 20; p = new Product("Cuccumber", 40); } } class Product { public string ProductName { get; set; } public decimal Rate { get; set; } public Product( string name,decimal price ) { Rate = price; ProductName = name; } } }
Parameter Passing
There are four different kinds of parameters in C#: value parameters (the default), reference parameters (which use the ref modifier), output parameters (which use the out modifier), and parameter arrays (which use the params modifier). You can use any of them with both value and reference types. When you hear the words "reference" or "value" used (or use them yourself) you should be very clear in your own mind whether you mean that a parameter is a reference or value parameter, or whether you mean that the type involved is a reference or value type. If you can keep the two ideas separated, they're very simple.
1. Value parameters With their Type as Reference Type:
By default, parameters are value parameters. This means that a new storage location is created for the variable in the function member declaration, and it starts off with the value that you specify in the function member invocation. If you change that value, that doesn't alter any variables involved in the invocation. For instance, if we have:
class ValueTypeRefTypeExercises { static void Main(string[] args) { StringBuilder y = new StringBuilder(); y.Append("Hello"); Foo(y); Console.WriteLine(y == null); Console.ReadLine(); } static void Foo(StringBuilder x) { x = null; } }
As discussed in the first example code it's not possible to change the type of reference object to a new address in a function with a value parameter.
The value of y isn't changed just because x is set to null. Remember though that the value of a reference type variable is the reference - if two reference type variables refer to the same object, then changes to the data in that object will be seen via both variables. For example:
class ValueTypeRefTypeExercises { static void Main(string[] args) { StringBuilder y = new StringBuilder(); y.Append("Hello"); Foo(y); Console.WriteLine(y); Console.ReadLine(); } static void Foo(StringBuilder x) { x.Append(" world"); } }
2. Value parameters With their Type as Value Type:
Now consider what happens when value types are passed by value. As I said before, the value of a value type variable is the data itself. Using the previous definition of the struct IntHolder, let's write some code similar to the above:
void Foo (IntHolder x) { x.i=10; } ... IntHolder y = new IntHolder(); y.i=5; Foo (y); Console.WriteLine (y.i);
Output: 5
When Foo is called, x starts off as a struct with value i=5. Its i value is then changed to 10. Foo knows nothing about the variable y, and after the method completes, the value in y will be exactly the same as it was before (i.e. 5).
3. Ref Parameter with their Type as Reference Type:
Reference parameters don't pass the values of the variables used in the function member invocation - they use the variables themselves. Rather than creating a new storage location for the variable in the function member declaration, the same storage location is used, so the value of the variable in the function member and the value of the reference parameter will always be the same. Reference parameters need the ref modifier as part of both the declaration and the invocation - that means it's always clear when you're passing something by reference. Let's look at our previous examples, just changing the parameter to be a reference parameter:
void Foo (ref StringBuilder x) { x = null; } ... StringBuilder y = new StringBuilder(); y.Append ("hello"); Foo (ref y); Console.WriteLine (y==null);
Output: True
4. Ref Parameter with their Type as Value Type:
Now consider the struct code we had earlier, but using reference parameters:
void Foo (ref IntHolder x) { x.i=10; } ... IntHolder y = new IntHolder(); y.i=5; Foo (ref y); Console.WriteLine (y.i);Output: 10
The two variables are sharing a storage location, so changes to x are also visible through y, so y.i has the value 10 at the end of this code.
what is the difference between passing a value object by reference and a reference object by value?
You may have noticed that the last example, passing a struct by reference, had the same effect in this code as passing a class by value. This doesn't mean that they're the same thing, however. Consider the following code:
void Foo (??? IntHolder x) { x = new IntHolder(); } ... IntHolder y = new IntHolder(); y.i=5; Foo (??? y);
In the case where IntHolder is a struct (i.e. a value type) and the parameter is a reference parameter (i.e. replace ??? with ref above), y ends up being a new IntHolder value -
i.e. y.i is 0. In the case where IntHolder is a class (i.e. a reference type) and the parameter is a value parameter (i.e. remove ??? above), the value of y isn't changed - it's
a reference to the same object it was before the function member call. This difference is absolutely crucial to understanding parameter passing in C#, and is why I believe it is highly confusing to say that objects are passed by reference by default instead of the correct statement that object references are passed by value by default.
Conclusions:
1. When designing your own API, I would strongly advise you to almost never use ref or out parameters. They can be useful occasionally, but usually they're an indication that you're trying to return multiple values from a single method, which is often better done with a type specifically encapsulating those values, or perhaps a Tuple type if you're using .NET 4. There are exceptions to this rule, of course, but it's a good starting point.
2. When possible, you should use value types instead of reference types because your application's performance will be better. In particular, you should declare a type as a value type if all of the following are true:
The type acts like a primitive type.
The type doesn't need to inherit from any other type.
The type will not have any other types derived from it.
Objects of the type are not frequently passed as method arguments since this would cause frequent memory copy operations, hurting performance.
References:
5 comments:
Hi, I do think this is a great blog. I stumbledupon it ;) I will revisit yet again since i have book marked
it. Money and freedom is the best way to change, may you be rich and continue to guide other people.
My webpage: quick cash
Hello it's me, I am also visiting this website regularly, this site is truly nice and the visitors are in fact sharing nice thoughts.
My homepage - http://www.1worldsarongs.com/
Hi to every body, it's my first go to see of this webpage; this website includes awesome and genuinely good information designed for readers.
Feel free to visit my page - Www.Articlerich.Com
Hello There. I discovered your weblog the use of msn. That
is an extremely smartly written article. I will make
sure to bookmark it and come back to learn extra of your useful
information. Thank you for the post. I'll definitely comeback.
Here is my weblog :: www.articlerich.com
Hello there, I think your site could possibly be having internet
browser compatibility problems. When I take a look at your site in Safari,
it looks fine however when opening in Internet Explorer, it's got some overlapping issues.
I simply wanted to give you a quick heads up! Aside from that, fantastic site!
Here is my web-site; cure yeast infection fast
Post a Comment