4

I would like to use a function that has a parameter of type A. I would like to pass it a class B which derived from A. But C# does not want to.

class A
{
 int m_a;
}

class B : A
{
 int m_b;
}

void ShowandEditData( ref A _myvar)
{
 ...
}

Now, i would like to do something like this:

B myB = new B();

ShowandEditData(ref myB);

I have tried many things like casting or using the base attribute. I guess I'm doing it wrong.

Is it possible to do that with C#?

--Code Edited due to pseudocode creating confusion . (sorry, first post)

Xavier
  • 440
  • 4
  • 11

3 Answers3

6

just remove the ref from your method declaration. Like so:

void ShowData(A _myvar)
{
 ...
}
Klaus Byskov Pedersen
  • 117,245
  • 29
  • 183
  • 222
  • 1
    Why would a ref keyword be incorrect? Is it not rather the replacement between `Function` (OP) and `void` (answer) that is the solution? – Flater Feb 25 '14 at 14:23
  • @Flater, well yes and no. The question at the time of my answer did not have the `ref` in the method call, only in the declaration. It is correct that `Function` is not a keyword in c#, so obviously there were several problems. – Klaus Byskov Pedersen Feb 25 '14 at 14:38
2

You have to use the ref keywork on the call of method:

ShowData(ref myB);

Actually, classes in is reference values, so you do not need to use ref. Use ref just for value types (structs like int, short, double, decimal, bool, DateTime etc..) when you really want to pass the reference.

In your case you just could use

object ShowData(A _myvar)
{
 ...
}
Felipe Oriani
  • 37,948
  • 19
  • 131
  • 194
  • Or, yet better, remove the `ref` in the function declaration. – Uwe Keim Feb 25 '14 at 14:14
  • Maybe OP wanted to mutate the caller's reference ? – StuartLC Feb 25 '14 at 14:16
  • I also need to update the object, this is why i need the reference – Xavier Feb 25 '14 at 14:17
  • But, in C# classes works as a reference types, but there is not problem to keep there. In the call of the method, you have to specify `ref` keywork as first my sample. – Felipe Oriani Feb 25 '14 at 14:18
  • 2
    I don't think that simply adding a `ref` to the call will work because if using `ref` and ShowData assigns a new value, it can assign any value to the variable that is A or derived from it, but it must not necessarily be compatible with the variable type which is B. Therefore, you can only call it with variables that are of type A. – Markus Feb 25 '14 at 14:19
  • "Actually, classes in c# is reference values, so you do not need to use ref." `ref` works the same way for all types. Therefore you "need" it in the same situations regardless of type. – newacct Feb 26 '14 at 06:48
  • @newacct Yes, I just want to emphasize the classes already works as a reference types. I also said that values types works with ref, but thanks for command when addind -1 :) – Felipe Oriani Feb 26 '14 at 11:16
2

The ref keyword doesn't support polymorphicism

If you can change the signature of ShowData, then I would suggest you change it like so:

  public A ShowData(A _myvar)
  {
     return new B();  // Or A() or whatever.
  }

And call like so:

B myB = new B();
myB = ShowData(myB);

Alternatively, you'll need to provide overloads of ShowData for both classes:

  public void ShowData(ref A _myvar)
  {
     _myvar = new B();
  }

  public  void ShowData(ref B _myvar)
  {
     _myvar = new B();
  }

Then the compiler can choose the overload:

     A myA = new A();
     B myB = new B();
     ShowData(ref myB);
     ShowData(ref myA);

As an aside, ShowData is not a good name. MutateData sounds more appropriate :-)

Community
  • 1
  • 1
StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • Indeed MutateData sounds better, I just copied the pseudocode from my Board. – Xavier Feb 25 '14 at 14:35
  • 1
    Indeed "polymorphism" is what I want to do. your link seems to confirm that this won't be possible with c#; but it's a shame. I will keep looking for a solution. – Xavier Feb 25 '14 at 14:39