0

I have four named variables:

float smoothPlusError = smoothAngle + angleError;
float smoothMinusError = smoothAngle - angleError;
float smoothMinus90 = smoothAngle - 90;
float smoothPlus90 = smoothAngle + 90;

I need to check if each of these variables is above or below a certain threshold and then adjust accordingly. To avoid repeating the same code four times, I am trying to do this in a loop as follows:

float[] angles = { smoothPlusError, smoothMinusError, smoothMinus90, smoothPlus90 };

for (int i = 0; i < angles.Length; i++)
{ 
  if (angles[i] > 360)
      angles[i] -= 360;
  else if (angles[i] < 0)
      angles[i] += 360;
}

The problem with this approach is that the array creates copies of the named variables and updating the values in the array does not update the original named variables.

Please advise how I can pass named variables to an array and update their original values?

7
  • You'd need to create an object and use a float field there. But: why not create a method that does the angle correction and apply that function inplace? Commented Mar 26, 2021 at 15:54
  • You could always do smoothPlusError = angles[0]; after the loop, though a method you apply to each would be a better idea. Commented Mar 26, 2021 at 15:57
  • I guess I could create and apply a method. That seems quite long winded though. Does this mean we cannot pass actual values (aka references) to arrays and edit them directly? Commented Mar 26, 2021 at 15:58
  • @Cato Yes, you can use ref. Commented Mar 26, 2021 at 15:59
  • 1
    @Johnathan How can this be done? Can you demonstrate the syntax please? Commented Mar 26, 2021 at 16:02

6 Answers 6

1

You can't with value types (and float is one). Value type variables hold the value directly (not a reference to where the value is), so, except for one case (passing a ref parameter to a method), it's not possible in C# to have two value-typed variables to point to the same position in memory.

So you either use a method (and use ref), or create a reference type (a class with a float property or field)

Sign up to request clarification or add additional context in comments.

Comments

1

You could put the float into an object and then change it there. I would not recommend boxing and unboxing without a user defined type.

class AngleRef
{
    internal AngleRef(float angle) {this.angle=angle;}
    internal float angle;
}

public void Main()
{
    float smoothAngle = 6;
    float angleError = 2;
    var smoothPlusError = new AngleRef(smoothAngle + angleError);
    var smoothMinusError = new AngleRef(smoothAngle - angleError);
    var smoothMinus90 = new AngleRef(smoothAngle - 90);
    var smoothPlus90 = new AngleRef(smoothAngle + 90);
    
    AngleRef[] angles = { smoothPlusError, smoothMinusError, smoothMinus90, smoothPlus90 };
    
    for (int i = 0; i < angles.Length; i++)
    { 
      if (angles[i].angle > 360)
          angles[i].angle -= 360;
      else if (angles[i].angle < 0)
          angles[i].angle += 360;
    }
}

Comments

1

Please advise how I can pass named variables to an array and update their original values?

It can't be done with value types, though I suppose it depends on whether you'll accept the fudge of turning the value types into reference types. One such fudge is to put things in single element arrays:


float[] smoothPlusError = new[]{smoothAngle + angleError};
float[] smoothMinusError = new[]{smoothAngle - angleError};
float[] smoothMinus90 = new[]{smoothAngle - 90};
float[] smoothPlus90 = new[]{smoothAngle + 90};


float[][] angles = { smoothPlusError, smoothMinusError, smoothMinus90, smoothPlus90 };

for (int i = 0; i < angles.Length; i++)
{ 
  if (angles[i][0] > 360)
      angles[i][0] -= 360;
  else if (angles[i][0] < 0)
      angles[i][0] += 360;
}

[0] basically then "becomes part of the variable name" everywhere you go:

Console.WriteLine(smoothPlusError[0]);
                  ^^^^^^^^^^^^^^^^^^
               Consider it the entire name

It's a seldom used but occasionally handy trick if you want to get value types to behave referency without declaring a dedicated ref type

The other thing I mentioned in the comments is potentially more useful:

public class SomeFloats{

  private float[] angles = new float[4];

  public float SmoothPlusError { get => angles[0]; set => angles[0] = value; }
  public float SmoothMinusError { get => angles[1]; set => angles[1] = value; }
  public float SmoothMinus90 { get => angles[2]; set => angles[2] = value; }
  public float SmoothPlus90 { get => angles[3]; set => angles[3] = value; }

  public void FixThem(){
    for (int i = 0; i < angles.Length; i++)
    { 
      if (angles[i] > 360)
        angles[i] -= 360;
      else if (angles[i] < 0)
        angles[i] += 360;
    }
  }
}

You can still hence access these in an array-ey way internally (or externally if you want to expose it), but also refer to them by name in the code

    var sf = new SomeFloats(){ SmoothPlusError = 362 };
    sf.FixThem();
    Console.WriteLine(sf.SmoothPlusError); //2

Comments

0

Try like below

float smoothPlusError = GetAngle(smoothAngle + angleError);
float smoothMinusError = GetAngle(smoothAngle - angleError);
float smoothMinus90 = GetAngle(smoothAngle - 90);
float smoothPlus90 = GetAngle(smoothAngle + 90);

private float GetAngle(float angle)
{
  if (angle > 360)
    return  angle -= 360;
  else if (angle < 0)
     return angle += 360;
     else
     return angle;
}

Comments

0

The best solution is @MekalaV's: refactor the code into a method. But it seems you want to do it in-place, so you can use a ref parameter.

float smoothPlusError = smoothAngle + angleError;
float smoothMinusError = smoothAngle - angleError;
float smoothMinus90 = smoothAngle - 90;
float smoothPlus90 = smoothAngle + 90;

AdjustAngle(ref smoothPlusError);
AdjustAngle(ref smoothMinusError);
AdjustAngle(ref smoothMinus90);
AdjustAngle(ref smoothPlus90);
private void AdjustAngle(ref float angle)
{
  if (angle > 360)
    angle -= 360;
  else if (angle < 0)
    angle += 360;
}

Comments

0

EDIT: You can use an array with the ref keyword too:

    float smoothPlusError = smoothAngle + angleError;
    float smoothMinusError = smoothAngle - angleError;
    float smoothMinus90 = smoothAngle - 90;
    float smoothPlus90 = smoothAngle + 90;

    float[] angles = { smoothPlusError, smoothMinusError, smoothMinus90, smoothPlus90 };

    for (int i = 0; i < 4; i++)
        AdjustAngle(ref angles[i]);

    private static void AdjustAngle(ref float angle)
    {
        if (angle > 360)
            angle -= 360;
        else if (angle < 0)
            angle += 360;
    }

You could create a simple class so it will be a reference type:

class RefType<T>
{
    T Value { get; set; }

    public RefType(T value)
    {
        Value = value;
    }
}

Then have your array:

RefType<float> smoothPlusError = new RefType<float>(smoothAngle + angleError);
RefType<float> smoothMinusError = new RefType<float>(smoothAngle - angleError);
RefType<float> smoothMinus90 = new RefType<float>(smoothAngle - 90);
RefType<float> smoothPlus90 = new RefType<float>(smoothAngle + 90);

RefType<float>[] angles = { smoothPlusError, smoothMinusError, smoothMinus90, smoothPlus90 };

Then loop with:

foreach (var angle in angles)
{
    if (angle.Value > 360)
        angle.Value -= 360;
    else if (angle.Value < 0)
        angle.Value += 360;
}

An alternative solution would be to have the array as you main location for the angles and instead of variables storing the angles, they would instead be array indices:

int smoothPlusError = 0;
int smoothMinusError = 1;
int smoothMinus90 = 2;
int smoothPlus90 = 3;

float[] angles = new float[]
{
    smoothAngle + angleError,
    smoothAngle - angleError,
    smoothAngle - 90,
    smoothAngle + 90
}

So you can use your existing loop to update the angles and refer to the specific variables as:

angles[smoothPlusError] = ...;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.