0

I have read the article about multiple returns a number of times. But I cannot figure out how to apply it when the values that I am trying to get out are not be destructed into simple scalars, but rather object properties. (I can use C# V7 if needed).

Also the out keyword is not allowed when with parameters that are object properties. So how can I do this example:

Tools.orientation(ent.esr, out e.heading, out e.pitch, out e.roll);

//...

public static void orientation(EntityStateRepository esr, out double  heading, out double pitch, out double roll)
{
    TaitBryan topoEuler = topoToGeoc.eulerTrans(esr.worldOrienation);
    heading = MathHelper.RadiansToDegrees(topoEuler.psi);
    pitch = MathHelper.RadiansToDegrees(topoEuler.theta);
    roll = MathHelper.RadiansToDegrees(topoEuler.phi);
}
Dr.YSG
  • 7,171
  • 22
  • 81
  • 139
  • 9
    I think you are over thinking this. Define a new type with those properties and return an instance of that type. – Igor Oct 03 '17 at 20:12
  • The function is only filling in a few of those values, should I just pass in the object and let it do the rest? – Dr.YSG Oct 03 '17 at 20:13
  • @Dr.YSG the parameter should be the object, the return value should be the object. Modify it in the method, then return the modified object. – maccettura Oct 03 '17 at 20:15
  • What about [`ValueTuples`](https://blogs.msdn.microsoft.com/mazhou/2017/05/26/c-7-series-part-1-value-tuples/) in C# 7? – Salah Akbari Oct 03 '17 at 20:21
  • I was using ValueTuples, but it looked a little verbose for me to first deconstruct the Tuple, and then stuff it into the Entry.e object. I think I am going with @maccettura approach, which I just compiled and ran. – Dr.YSG Oct 03 '17 at 20:27
  • @Dr.YSG My approach is the same as Igors answer. – maccettura Oct 03 '17 at 20:28

3 Answers3

3

I think you are over thinking this. Define a new type with those properties and return an instance of that type. For example:

public static OrientationModel orientation(EntityStateRepository esr)
{
    TaitBryan topoEuler = topoToGeoc.eulerTrans(esr.worldOrienation);
    var container = new OrientationModel();

    container.heading = MathHelper.RadiansToDegrees(topoEuler.psi);
    container.pitch = MathHelper.RadiansToDegrees(topoEuler.theta);
    container.roll = MathHelper.RadiansToDegrees(topoEuler.phi);

    return container;
}

public sealed class OrientationModel {
    public decimal heading {get;set;}
    public decimal pitch {get;set;}
    public decimal roll {get;set;}
}
Igor
  • 60,821
  • 10
  • 100
  • 175
  • 1
    @xxbbcc - True, it was meant as an example but maybe this is more clear. – Igor Oct 03 '17 at 20:16
  • @Igor why use `ref` parameters at all? The OP is trying to pass properties by reference - why not just pass the object in instead of the properties? – D Stanley Oct 03 '17 at 20:17
  • @DStanley - because I got sloppy with my copy/paste and read past it. More on your point though they are not used at all so they could just be omitted. – Igor Oct 03 '17 at 20:18
  • @DStanley I think Igor just forgot to change the parameters from the OP code – maccettura Oct 03 '17 at 20:19
2

You can't pass properties by reference, so your best bet is to pass in the parent object instead:

Tools.orientation(ent.esr, e);

//...

public static void orientation(EntityStateRepository esr, TypeOfE e)
{
    TaitBryan topoEuler = topoToGeoc.eulerTrans(esr.worldOrienation);
    e.heading = MathHelper.RadiansToDegrees(topoEuler.psi);
    e.pitch = MathHelper.RadiansToDegrees(topoEuler.theta);
    e.roll = MathHelper.RadiansToDegrees(topoEuler.phi);
}

Or if you want to keep the version with out parameters and add an overload instead:

public static void orientation(EntityStateRepository esr, TypeOfE e)
{
    double heading;
    double pitch;
    double roll;
    Tools.orientation(ent.esr, out heading, out pitch, out roll);
    e.heading = heading;
    e.pitch = pitch;
    e.roll = roll;
}
//...

public static void orientation(EntityStateRepository esr, out double  heading, out double pitch, out double roll)
{
    TaitBryan topoEuler = topoToGeoc.eulerTrans(esr.worldOrienation);
    heading = MathHelper.RadiansToDegrees(topoEuler.psi);
    pitch = MathHelper.RadiansToDegrees(topoEuler.theta);
    roll = MathHelper.RadiansToDegrees(topoEuler.phi);
}
D Stanley
  • 149,601
  • 11
  • 178
  • 240
2

Just for completeness sake, you mentioned multiple return types.

With C# 7 features, and the NuGet Package System.ValueTuple you could write the following, and it would be equivalent to Igor's answer unless you are going to re-use the SomeContainer class

public static (double heading, double pitch, double roll) orientation(EntityStateRepository esr)
{
    TaitBryan topoEuler = topoToGeoc.eulerTrans(esr.worldOrienation);

    var h = MathHelper.RadiansToDegrees(topoEuler.psi);
    var p = MathHelper.RadiansToDegrees(topoEuler.theta);
    var r = MathHelper.RadiansToDegrees(topoEuler.phi);

    return (h, p, r);
}

And access with

var res = orientation(...);
DoAThing(res.heading);
DoAThing(res.pitch);
DoAThing(res.roll);
Adam Schiavone
  • 2,412
  • 3
  • 32
  • 65