0

I can't understand this code, here the same implementation for the DataSet object and string variable, but different output,.I can see the logic behind the output of the string variable, but for the DataSet, I can't understand why!

class Program
    {

        static void Main(string[] args)
        {
            DataSet ds = new DataSet();
            FillDS(ds);
            PrintDS(ds);
            string name = "old";
            AssignString(name);
            PrintString(name);
        }
        private static void AssignString(string name)
        {
            name = "new name";
        }
        private static void PrintString(string name)
        {
            Console.WriteLine(name);
        }
        private static void FillDS(DataSet ds)
        {
            ds.Tables.Add(new DataTable("tbl1"));
            ds.Tables.Add(new DataTable("tbl2"));
        }
        private static void PrintDS(DataSet ds)
        {
            foreach (DataTable item in ds.Tables)
            {
                Console.WriteLine(item.TableName);
            }
        }
    }
//Output:
//tbl1
//tbl2
//old
mshwf
  • 7,009
  • 12
  • 59
  • 133
  • By "same implementation", you mean what? In `AssignString` you're assigning a new value to the `name` parameter. In `FillDS`, you are NOT assigning anything to the `ds` parameter. You are calling methods on it which change its contents. Can you see that the two actions are not the same? If you assigned `ds = new DataSet()` inside `FillDS`, you would find that the dataset you passed in as a parameter would not have changed. – 15ee8f99-57ff-4f92-890c-b56153 Aug 16 '16 at 14:11
  • I may not assign new value to the parameter passed to AssignString, I may do so: name.Remove(0, 1); output: old – mshwf Aug 16 '16 at 14:22
  • they are both reference type, why for string it doesn't take a copy from the original, but take a copy from the dataset? BTW the result still the same if I replaced string with int – mshwf Aug 16 '16 at 14:23
  • Read the [documentation for String.Remove](https://msdn.microsoft.com/en-us/library/system.string.remove(v=vs.110).aspx). It doesn't alter the string, it just returns a new one. It happens that String has no methods that alter it; all of them just return new strings that are different. – 15ee8f99-57ff-4f92-890c-b56153 Aug 16 '16 at 14:24
  • Try this code in your `Main` function: `var s = "test"; s.Remove(0,1); Console.WriteLine(s);`. You will find that `String.Remove()` never changes the string. Then try this: `var s2 = s.Remove(0,1); Console.WriteLine(s2);` You will find that `String.Remove()` RETURNS a different string from the original. But it does not change the original. – 15ee8f99-57ff-4f92-890c-b56153 Aug 16 '16 at 14:28

3 Answers3

7

Strings are immutable, plus you are not modifying the string parameter (not that you can), but instead you are assigning a new reference to your parameter. The original remains in place.

With DataSet, you are modifying its contents and since it is a mutable reference type, you see the change in the caller.

Try the following in Main

    DataSet ds = new DataSet();
    ds.Tables.Add(new DataTable("tbl3"));
    FillDS(ds);

and then in FillDS assign a new reference to your DataSet like:

private static void FillDS(DataSet ds)
{
    ds = new DataSet(); //Here 
    ds.Tables.Add(new DataTable("tbl1"));
    ds.Tables.Add(new DataTable("tbl2"));
}

You will see that your DataSet still holds the old values and nothing is modified after calling FillDS

Habib
  • 219,104
  • 29
  • 407
  • 436
  • How can I tell that a type is mutable or not? I found that `int` is immutable too! – mshwf Aug 16 '16 at 14:36
  • 1
    Docs... See these [blog posts](https://blogs.msdn.microsoft.com/ericlippert/tag/Immutability/) by Eric Lippert – Habib Aug 16 '16 at 14:38
6

Both string and DataSet are reference types. So in both cases you pass references.

In the AssignString method, you don't change the string instance you passed, but assign a new instance ("new name") to the variable name. The fact that the name variable actually was a parameter does not matter (though it's considered a bad practice to re-assign parameters).

In FillDS you do not reassign a new instance, but access and manipulate the properties of the passed instance via ds.Tables.....

René Vogt
  • 43,056
  • 14
  • 77
  • 99
  • so is there properties in `string` type that can do the same as `DataSet` in this example? – mshwf Aug 16 '16 at 14:27
  • 1
    @MohamedAhmed No. `string` has been designed to be _immutable_. Every possible operation on a `string` instance returns a _new_ instance with the changed value, but does not change the current instance. – René Vogt Aug 16 '16 at 14:28
  • Is there a subject/ topic for mutable and immutable types in C#? I think I didn't touch this topic before – mshwf Aug 16 '16 at 14:30
  • because I found that `int` type behave the same as `string` in this example, How to tell that a type is mutable or not? – mshwf Aug 16 '16 at 14:32
  • @MohamedAhmed "(Im-)mutability" is an implementation detail or a convention. A class with _instance_ properties or fields that can be changed is called mutable. If the properties or fields cannot be changed during the lifetime of an instance, the type is called immutable. There's nothing more about it. For more information on that topic you can simply google "c# immutable". Some developers have a philosophy of making all their types immutable if possible. Others disagree or don't care. Note that `int` is different since it is a _value_ type and not a _reference_ type like `string`. – René Vogt Aug 16 '16 at 14:37
  • @RenéVogt, just to add, a value type could be immutable too. – Habib Aug 16 '16 at 14:39
  • Is making fields of a class readonly make that class immutable? is that how i can create immutable types? – mshwf Aug 16 '16 at 14:42
  • 1
    @MohamedAhmed it's a start, as I said, google is your friend...I'd start with the second search result: https://blogs.msdn.microsoft.com/ericlippert/2007/11/13/immutability-in-c-part-one-kinds-of-immutability/ – René Vogt Aug 16 '16 at 14:46
0

Because DataSet and string both are reference types, and in reference types it is always the memory address of the object that is passed where it lives on the managed heap.

Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160