Wondering
Wondering

Reputation: 5076

ref type and value type in Generic

I was working on a demo method and found something strange(at least to me :-))

enter code here  class Program
{
    public void AnotherSwap<T>(T a, T b)  
    {
        T temp;
        temp = a;
        a = b;
        b = temp;

        Console.WriteLine(a);
        Console.WriteLine(b);

    }


    public void swap<T>(T a, T b) where T : MyInt  // Passing without ref
    {
        object temp;
        temp = a.MyProperty;
        a.MyProperty = b.MyProperty;
        b.MyProperty = (int)temp;

        Console.WriteLine(a.MyProperty);
        Console.WriteLine(b.MyProperty);



    }

    static void Main(string[] args)
    {
        Program p = new Program();
        MyInt a = new MyInt() { MyProperty = 10 };
        MyInt b = new MyInt() { MyProperty = 20 };
        p.swap<MyInt>(a, b);
        Console.WriteLine(a.MyProperty); // changed values get reflected
        Console.WriteLine(b.MyProperty); // changed values get reflected

        Console.WriteLine("Another Swap");
        object x = 10;
        object y = 20;
        p.AnotherSwap(x, y);

        Console.WriteLine(x);  // changed values are not getting  reflected
        Console.WriteLine(y);  // changed values are not getting  reflected

         Console.ReadKey();


    }
   public class MyInt
    {
        public int MyProperty { get; set; }

    }




}

Here when I am calling the swap() , though I haven't mentioned ref , the changed values are automatically getting reflected (as in p.swap(a, b); a and b are instance of Myint and thus will by default work as ref..as per my understanding.) But same should happen with Anotherswap() here also I am passing object x,y but now the values are not getting reflected in Main() .i.e. now its working as a value type. Can somebody explain where my understanding is going wrong. Let me know if u guys want more info.

Upvotes: 0

Views: 960

Answers (3)

kay.one
kay.one

Reputation: 7692

the second set of the objects [object x = 1] is converted to int which is a value type since it is assigned an int at initialization, so it is treated as an int which is a value type.

if you run the following snippet you'll see my point.

object test = 1;
Console.Writeline(test.GetType());

returns: "typeof (Int32)"

so the type of your object is no longer object but Int32 which is a value type.

object test = 1;
Console.Writeline(test.GetType().IsByRef);

returns: "false"

Upvotes: 1

scwagner
scwagner

Reputation: 4005

Your question is misleading, and the answer is actually simpler than that:

In your Swap function, you are swapping the values of the MyProperty properties in those classes, not the actual classes themselves. This would be easily proved if you had another property in the MyInt class called "Name" or something. After the call to Swap, you would see that the Name property remained unchanged.

The reason that in AnotherSwap nothing interesting is happening is because you aren't passing the types by ref at all, so the assignments that you perform to the object's pointer inside the function don't modify the original objects' pointers from the caller's perspective.

Something else to consider is that when you're turning 10 into an object, you're actually boxing the object, and that's something else you need to keep in mind. When writing generics that you want to behave differently for reference versus value types, I always just use "where T : class" for reference types and "where T : struct" for value types. The names of the two functions cannot be the same though.

Upvotes: 3

DevelopingChris
DevelopingChris

Reputation: 40788

When MyInt type is cast as Object, it gets cast as a val type. Object cannot be treated like a reference since its representing both val and ref, it must be explicitly passed by ref.

int can be cast as an object, and its still treated as a val. string can be cast as object, and its treated as a val. Even though normally it would be a ref type.

If you did the AnotherSwap and passed T in as MyInt, you would get the same results as before. If you called the original swap algorithm with objects, you would get the same output as the latter.

Upvotes: 1

Related Questions