简体   繁体   English

C# - 将命名变量添加到数组并更改其原始值(不是副本!)

[英]C# - Adding named variables to an array and changing their original values (not copies!)

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?请告知我如何将命名变量传递给数组并更新它们的原始值?

You can't with value types (and float is one).您不能使用值类型(而float就是其中之一)。 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.值类型变量直接保存值(不是对值所在位置的引用),因此,除了一种情况(将ref参数传递给方法),在 C# 中不可能有两个值类型变量指向memory 中的 position 相同。

So you either use a method (and use ref ), or create a reference type (a class with a float property or field)因此,您要么使用方法(并使用ref ),要么创建引用类型(具有float属性或字段的 class)

You could put the float into an object and then change it there.您可以将浮动放入 object 中,然后在此处更改。 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;
    }
}

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:一种这样的软糖是将东西放入单个元素 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: [0]基本上然后在 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如果您想在不声明专用 ref 类型的情况下让值类型表现引用,这是一个很少使用但偶尔会很方便的技巧

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

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;
}

EDIT: You can use an array with the ref keyword too:编辑:您也可以使用带有 ref 关键字的数组:

    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 所以它将是一个引用类型:

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] = ...;

The best solution is @MekalaV's: refactor the code into a method.最好的解决方案是@MekalaV:将代码重构为方法。 But it seems you want to do it in-place, so you can use a ref parameter.但似乎您想就地执行此操作,因此您可以使用ref参数。

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM