【问题标题】:get parameter value from IEnumerator function instance从 IEnumerator 函数实例获取参数值
【发布时间】:2020-04-07 22:34:47
【问题描述】:

假设我有一个IEnumerators 的列表:

public List<IEnumerator> routines;

假设我有这个枚举:

public enum Shape { CIRCLE, TRIANGLE, SQUARE }

我有很多IEnumerator 例程接收Shape 作为参数:

public IEnumerator Move(Shape shape, float distance){ /* code */ }
public IEnumerator Jump(Shape shape, float height){ /* code */ }
public IEnumerator Fire(Shape shape, float power){ /* code */ }

我的列表routines 将包含这些函数的一系列实例(稍后将使用StartCoroutine 调用):

routines.Add(Move(Shape.SQUARE, 1));
routines.Add(Jump(Shape.CIRCLE, 1));
routines.Add(Fire(Shape.TRIANGLE, 1));
//...

鉴于我已经用所有这些函数填充了 routines,有没有办法让我遍历 routines 并找出每个函数调用的 Shape 参数?在这种情况下,它将是 SQUARE、CIRCLE、TRIANGLE 等。

【问题讨论】:

  • 你需要Expression&lt;...&gt;(表达式树)——它存在于Unity3d中吗?
  • 是的,来自System.Linq.Expressions
  • 所以使用表达式作为 .Add 的参数而不是 Action&lt;Shape, int&gt; - 你不能反编译 lambdas 来提取参数,但你可以编译表达式来运行它们(并且确实可以提取参数)跨度>

标签: c# unity3d ienumerator


【解决方案1】:

如果您的枚举器实现支持“形状”,那么您可以从routines 投射项目并获得形状。

public interface IShapedEnumerator : IEnumerator {
  Shape EnumeratorShape {get; }
}

pblic class ShapedIteratorProxy : IShapedEnumerator {
  private readonly IEnumerator _baseEnumerator;
  private readonly Shape _shape;
  public Shape EnumeratorShape => _shape;

  public ShapedIteratorProxy (Shape shape, IEnumerator baseEnumerator) {
    _baseEnumerator = baseEnumerator;
    _shape = shape;
  }

  public ShapedIteratorProxy (Shape shape, float arg, Func<Shape, float, IEnumerator> operation)
    : this(shape, operation(shape, arg)) 
  {}
  // implementation of IEnumerator that proxy all calls to _baseEnumerator.
  // ...
}

routines.Add(new ShapedIteratorProxy(Shape.SQUARE, Move(Shape.SQUARE, 1)));
routines.Add(new ShapedIteratorProxy(Shape.CIRCLE, 1, Jump);
routines.Add(new ShapedIteratorProxy(Shape.TRIANGLE, 1, Fire);

var shapes = routines.OfType<IShapedEnumerator>()
                     .Select(s=>s.EnumeratorShape)
                     .ToArray();

请注意,如果routines 包含未实现IShapedEnumerator 的项目,它们将被跳过。

【讨论】:

  • 我没有运行Move,而是只创建它的一个实例,所以我认为这不适用,但也许我可以创建一个包含形状和 IEnumerator 属性的类接收这些函数(如Move)并在构造函数中全部设置...
  • 在你的问题中你打电话给routines.Add(Move(Shape.SQUARE, 1));,所以它被调用了。我不明白你在creating an instance of it instead 下的意思。 IEnumerator 不是属性,这是接口,Move 返回实现此接口的类的实例。不确定我是否在此评论中关注您的担忧。请详细说明。我将答案更改为不更改Move() 方法
  • 在 Unity 中,IEnumerator 仅在您使用 StartCoroutine 调用时才会执行(例如 StartCoroutine(Move(Shape.SQUARE, 1)))。
  • IEnumerator is not an attribute, this is interface and Move returns and instance of class that implements this interface. 虽然在技术上是正确的,但它不是这样工作的。 IEnumerator 的目的是执行一些代码,点击yield 并在稍后返回。当您调用Move() 时,代码会立即 执行,而您存储在数组中的只是一个指向“暂停”代码的指针。我认为您正在寻找 delegates、Actions 或事件。
猜你喜欢
  • 1970-01-01
  • 2020-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-26
相关资源
最近更新 更多