6

我不太确定我正在尝试做什么,所以我很难从谷歌中找到任何线索。

我有几个具有相同逻辑的方法,唯一不同的是它们在对象上使用的属性。

class Foo
{
   public int A(Bar bar)
   {
      return bar.A * 2;
   }

   public int B(Bar bar)
   {
      return bar.B * 2;
   }

   public int C(Bar bar)
   {
      return bar.C * 2;
   }
}

class Bar
{
   public int A;
   public int B;
   public int C;
}

而不是我想要的三个单独的方法Foo,其签名看起来更像

public int X(Bar bar, ??? x)
{
   return bar.x * 2;
}

这可能吗?

4

11 回答 11

17

我第一次看错了这个问题,我的错。

你可以用反射做到这一点:

public int Method(Bar bar, string propertyName)
{
   var prop = typeof(Bar).GetProperty(propertyName);
   int value = (int)prop.GetValue(bar,null);
   return value * 2;
}

然后,你这样称呼它:

Method(bar,"A");

刚刚注意到在您的示例中, Bar 中的 3 个变量是公共实例变量。我假设您只是为您的示例执行此操作,但如果您的真实课程中确实是这种情况,请使用 Rex M 的方法。

于 2009-05-27T13:49:24.637 回答
11
internal class Program {
    private static void Main(string[] args) {
        var bar = new Bar {A = 1, B = 2, C = 3};
        Console.WriteLine(new Foo().X(bar, it => it.A));
        Console.WriteLine(new Foo().X(bar, it => it.B));

        // or introduce a "constant" somewhere
        Func<Bar, int> cFieldSelector = it => it.C;
        Console.WriteLine(new Foo().X(bar, cFieldSelector));
    }
}

internal class Foo {
    // Instead of using a field by name, give it a method to select field you want.
    public int X(Bar bar, Func<Bar, int> fieldSelector) {
        return fieldSelector(bar) * 2;
    }

    public int A(Bar bar) {
        return bar.A * 2;
    }

    public int B(Bar bar) {
        return bar.B * 2;
    }

    public int C(Bar bar) {
        return bar.C * 2;
    }
}

internal class Bar {
    public int A;
    public int B;
    public int C;
}
于 2009-05-27T14:02:26.060 回答
3

我会考虑使用匿名委托来获取您的价值。

public int X(Bar bar, Func<Bar,int> getIt)
{
   return getIt(bar) * 2;
}

然后这样称呼它:

var x = X(mybar, x=>x.A);
于 2009-05-27T14:06:36.880 回答
0

您可以使用反射来实现这一点。它会对性能产生一些影响

于 2009-05-27T13:52:07.877 回答
0

您可以使用 PropertyInfo 类通过反射检索所需的属性:https ://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-6099345.html

于 2009-05-27T13:53:21.290 回答
0
public int X(Bar bar, string target)
{
    object value = bar.GetType().GetField(target, BindingFlags.Public | BindingFlags.Instance).GetValue(bar);
    return (int)value * 2;
}
于 2009-05-27T13:56:56.213 回答
0

尝试使用反射。下面是一些简单的代码来实现效果。

using System.Reflection;    

public int X(Bar bar, FieldInfo x)
{
    return (int)x.GetValue(bar) * 2;
}

现在,您可以通过首先获取 Bar 上的一个字段的 FieldInfo 来调用 X。

Bar b = new Bar();
b.A = 20;
b.B = 30;
b.C = 40;

FieldInfo fieldA = typeof(Bar).GetField("A");
int result = X(b, fieldA);
于 2009-05-27T13:58:00.500 回答
0

使用字段信息

BindingFlags flags = BindingFlags.Instance | BindingFlags.Public;
FieldInfo field = typeof(Bar).GetField("A", flags);

field.SetValue(..) 设置值。

于 2009-05-27T13:59:02.370 回答
0

您可以使用扩展方法.. 对于您发布的示例.. 但我想您的示例只是一些更复杂代码的简化版本。

public static class IntExt
{
    //use Bar.A.Double();
    public int Double(this int value)
    {
        return value * 2;
    }
}
于 2009-05-27T14:04:09.380 回答
0

为什么不使用枚举并将其传递给函数以确定使用哪个?似乎反射有点向西环游世界,向右迈出一步......

class Foo
{
   public enum BarChoice { a,b,c };
   public int x(Bar bar, BarChoice bc)
   {
     switch(bc) 
     {
       case a:
         return bar.A * 2;
       case b:
         return bar.B * 2;
       case c:
         return bar.C * 2;
     }
     return int.MinValue;
   }
}

那么你的电话将是

 Foo f = new foo();
 Bar b = new Bar();
 f.x(b, Foo.BarChoice.a);
 f.x(b, Foo.BarChoice.b);
 f.x(b, Foo.BarChoice.c);
于 2009-05-27T14:06:07.520 回答
0

您可以使用以下ref关键字:

class Foo
{
    public void A(ref int fieldRef)
    {
        fieldRef *= 2;
    }
}

class Bar
{
    public int A;
    public int B;
    public int C;
}

class Program
{
    static void Main(string[] args)
    {
        var bar = new Bar { A = 1, B = 2, C = 3 };
        var foo = new Foo();
        foo.A(ref bar.A);
        foo.A(ref bar.B);
        foo.A(ref bar.C);

        Console.WriteLine(bar.A); // 2
        Console.WriteLine(bar.B); // 4
        Console.WriteLine(bar.C); // 6
    }
}

我已经更改了一些不切实际的示例(正如@Jonas Elfström 所说,在这种情况下您可以简单地传递值)。这表明您可以更改字段的值。

于 2020-08-19T18:00:59.360 回答