4

I have the following class:

public class SubStredisko
{
    public string Name { get; set; }
    public string Code { get; set; }

    public VyplatnePasky VyplatnaPaska { get; set; }
    public MzdoveNaklady MzdoveNaklady { get; set; }
    public Poistne Poistne { get; set; }
}

then I have two SubStredisko items, where one of them is definitely null. What I am trying to do, is that I have a separate method, which does some processing with SubStredisko, such as changes values of VyplatnaPaska etc. Here is what it looks like:

    private static void VyplatnePasky_Items(ref Stredisko stredisko, XElement myElement)
    {
        //some logic here
    }

What I try to do now (what I have problem with) is to call this method using the ?: operator in the following way:

VyplatnePasky_Items((sPracovisko == null) ? ref sPracovisko_Dohodari : ref sPracovisko,xElement);

However it highlights sPracovisko_Dohodari and sPracovisko with the following error: Syntax error, ':' expected.

I tried to put them in brackets separately, however with no luck. What am I doing wrong?

P.S. sPracovisko and sPracovisko_Dohodari are of type SubStredisko.

P.S.2: Just a quick thought - maybe I don't even need a ref parameter in here? I am not quite sure if in this case a new object will be created, or I will be (in my void) directly changing values of that specific object.

Zachi Shtain
  • 826
  • 1
  • 13
  • 31
Robert J.
  • 2,631
  • 8
  • 32
  • 59
  • 2
    In that `VyplatnePasky_Items` method, are you assigning a new value to `stredisko`? If not, then you don't need thar ref, even if you *are* assigning new values to properties of that stredisko. – Hans Kesting Aug 20 '15 at 08:26
  • 1
    `SubStredisko` is a `class` (and not a `struct`), so it's a reference type. So if you just pass it like `(sPracovisko == null) ? sPracovisko_Dohodari : sPracovisko` (without the `ref`), then you will be able to manipulate the contents of the referenced object directly. So no "new object" will be created. The only thing you would need the `ref` keyword for would be if you want to be able to change what object the *variable* (`sPracovisko` or `sPracovisko_Dohodari`) references. – Corak Aug 20 '15 at 08:37
  • There are two issues. First, if both `sPracovisko` and `sPracovisko_Dohodari` are of type `Stredisko` you ***can*** now with C# 7 use the ternary operator: `VyplatnePasky_Items(ref (sPracovisko == null ? ref sPracovisko_Dohodari : ref sPracovisko), xElement)`. However, the more general problem is that you said that those types are `SubStredisko` rather than `Stredisko`, and you can't pass types by-reference unless they match the exact type. See [here](https://stackoverflow.com/a/45124463/147511) for explanation. – Glenn Slayden Jun 04 '18 at 00:30

4 Answers4

4

You can't use an expression for a ref parameter. You need two calls:

if (sPracovisko == null) {
  VyplatnePasky_Items(ref sPracovisko_Dohodari, xElement);
} else {
  VyplatnePasky_Items(ref sPracovisko, xElement);
}
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • Thank you for your answer. One additional questions (as P.S.2) - do I actually need a **ref** parameter in here? Will a new object be created without a **ref**? – Robert J. Aug 20 '15 at 08:27
  • @RobertJ.: You only need the `ref` parameter if you are going to assign something to the `sPracovisko_Dohodari`/`sPracovisko` variable inside the method. Without the `ref` keyword the parameter is sent by value, which means that a reference type is sent as a copy of the reference to the object. You will still be able to change the content in the object. – Guffa Aug 20 '15 at 09:03
  • See my comment above. With C# 7 you can now use **ref** in a ternary operator: `ref T a = ref (i == 0 ? ref b : ref c);`. (The r-value in this example can also be passed into `ref`-taking functions without needing to be assigned to a ref-local). – Glenn Slayden Jun 04 '18 at 00:33
  • ...And btw, can [also be used as an l-value](https://stackoverflow.com/a/50672315/147511), i.e. on the left-hand side of an assignment. – Glenn Slayden Jun 04 '18 at 01:10
2

As mentioned in the comments by @GlennSlayden, you can use ?: (ternary conditionals) with ref from C# 7 / VS2017, using the following syntax:

int a = 1;
int b = 2;
bool condition = true;

ref int i = ref (condition ? ref a : ref b);
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
1

The ref argument has to be a variable. It cannot be an ternary expression like you're trying to do. You can do this instead:

var inputParameter = sPracovisko == null ? sPracovisko_Dohodari : sPracovisko;
VyplatnePasky_Items(ref inputParameter, xElement);

Note that, with the code above, the changes will be reflected on the inputParamter, and it won't affect the other two variables. If you want the variables themselves to be changed, then go with @Guffa's answer.

Eren Ersönmez
  • 38,383
  • 7
  • 71
  • 92
  • I thought of this approach, however in this case we are creating one additional object in a memory, aren't we? This will be done in a loop and therefore I wanted to minimize memory consumption. – Robert J. Aug 20 '15 at 08:29
  • 2
    @RobertJ. no you're not creating an additional object. `SubStredisko` is a class; therefore, it is a _reference type_, which means it simply references the same object. – Eren Ersönmez Aug 20 '15 at 08:32
0

try this

VyplatnePasky_Items(((sPracovisko == null) ? ref sPracovisko_Dohodari :   sPracovisko),xElement);

or

VyplatnePasky_Items(((sPracovisko == null) ? ref sPracovisko_Dohodari :   sPracovisko) out,xElement);
Muks
  • 134
  • 9