0

Following on from my earlier question: c-sharp-convert-existing-class-to-use-properties-correctly

I have a class like this:

public class TestCaseInfo
{
    public string text { get; set; } = "";
    public string requirement_ref { get; set; } = "";
    public string given { get; set; } = "";
    public string when { get; set; } = "";
    public string then { get; set; } = "";
    public UInt32 timeLimit { get; set; } = 0;
}

I was previously populating the structure like this:

if (!getNodeValue(testcase_node.SelectSingleNode("text"), ref testcaseInfo.text))
    errStr += nodeError(testcase_node, "Missing 'text' node");

Note: that I am trying to pass it by reference. I have read a load of quetions that all basically say that you can't do this. Fair enough...

So I want to pass in the "real" value (I think its called the backing value?) instead. Something like:

if (!getNodeValue(testcase_node.SelectSingleNode("text"), ref testcaseInfo._text)) // where '_text' should be the 'backing' value.
    errStr += nodeError(testcase_node, "Missing 'text' node");

But I am missing two things (probably more!):

  1. What is the backing value called?
  2. I assume its private? - can I make it protected and make it a friend class? (that might be C++ talk... not sure if there is the same idea in C#)?
Community
  • 1
  • 1
code_fodder
  • 15,263
  • 17
  • 90
  • 167
  • this may become possible for auto properties in c#7? http://stackoverflow.com/documentation/c%23/1936/c-sharp-7-0-features/19197/ref-return-and-ref-local#t=201611071832375710367 Btw there are lots of strange things coming I don't like some of them :( – M.kazem Akhgary Nov 07 '16 at 18:33
  • @M.kazemAkhgary None of those features would be relevant to this problem. – Servy Nov 07 '16 at 18:34
  • @Servy I probably misunderstood. but if you can return value by ref then same thing could happen with getter of property (?) – M.kazem Akhgary Nov 07 '16 at 18:36
  • @M.kazemAkhgary well... if that's true it will be interesting.. but it would seem to break the rules if the backing value is meant to be private - then surely its not allowed? ... will have to take a look at this, thanks – code_fodder Nov 07 '16 at 18:38
  • 1
    @M.kazemAkhgary The feature is to allow *methods* to return references, not properties. It would break the contract of a property getter to return a reference anyway. The whole point of a property is that to set the value you need to use the setter. The *actual* feature to make this work would be to have some feature that allowed properties with both an accessible `get` and an accessible `set` to be treated as a reference, with the appropriate getter/setter used when the value is fetched/set. VB does this; C# makes you be explicit about it. – Servy Nov 07 '16 at 18:40
  • Thank you for the explanation. @Servy – M.kazem Akhgary Nov 07 '16 at 18:42

2 Answers2

5

There is no valid identifier for the backing field for that property. You could not use an auto property, and instead explicitly define the get and set methods of the property, along with your own backing field, thus giving you a valid identifier for the backing field, although it would be very poor design to expose this backing field externally.

What you should do is re-design your code such that you don't need to pass the value by reference in the first place. You should just be passing the string by value and, if the result of this function is the computation of a string, returning it. The caller can then set that string back to the property if that's what they want. That would be the more idiomatic design. (Since you also have a boolean value you'd need to pass both the string and the boolean out, of course.)

Servy
  • 202,030
  • 26
  • 332
  • 449
  • Ok awesome, I got it. I made a "intermediate" class that is not made of properties, but just has some public members (POD). This seems to work nicely as a data "passing" mechanism. Thanks for the pointer – code_fodder Nov 07 '16 at 18:42
  • 1
    @code_fodder You should not be doing that. That's not doing what I suggested at all. – Servy Nov 07 '16 at 18:43
  • Yeah I know but either way we need to use an "intermediate" step to store the data. Since there are lots of values, putting them all together makes sense to me. Probably my explanation is not that great either. – code_fodder Nov 07 '16 at 18:47
  • @code_fodder No, you don't actually need an intermediate step to store the data. As far as a place to put all of the data together, you already have that; it's the class you have in your question. You should be putting all of the values into *that*, not having a second one that's just like it but with public properties. – Servy Nov 07 '16 at 18:52
  • hmm...ok, but I can only return one parameter (which is a bool) and since I can't use ref or out then I don't understand how do that :( – code_fodder Nov 07 '16 at 19:03
  • @code_fodder There are a number of options, the simplest of which would be returning an object with two properties, a string and a boolean. – Servy Nov 07 '16 at 19:09
1

As far as you are concerned, your properties may as well not have backing fields. The backing field isn't called anything you can refer to if you didn't explicitly declare it:

private string _name;
public String Name { get { return _name; } set { _name = value; } }

If you write properties with explicit backing fields, as above, you can pass them by ref into a method.

private int _id;
public String ID { get { return int _id; } set { int _id = value; } }

public void Test()
{
    Int32.TryParse("Sausage Factory", out _id);
}
  • Ah I see - so there is a backing value, but unless you declaring it yourself you have no chance to get at it!.... I don't really want to do all this myself (got lots of classes to apply this to), so I am going with Servy's answer, but this is just as valid in my opinion, so thanks : ) – code_fodder Nov 07 '16 at 18:42
  • @code_fodder If it makes sense to redesign in order to do it his way, that's probably preferable. From your question, your design looked sensible enough for what you're doing. I've written some really weird code to hide the unpleasantness of grabbing values of XML elements that may or may not be there. – 15ee8f99-57ff-4f92-890c-b56153 Nov 07 '16 at 18:49