C# 如何对对象集合中的单个变量使用函数
我正在寻找一种方法,将函数应用于对象集合,每个对象同时具有多个变量,这样我就可以将函数应用于集合中的每个对象,并选择要应用函数的变量。例如: 上课C# 如何对对象集合中的单个变量使用函数,c#,function,reflection,C#,Function,Reflection,我正在寻找一种方法,将函数应用于对象集合,每个对象同时具有多个变量,这样我就可以将函数应用于集合中的每个对象,并选择要应用函数的变量。例如: 上课 point{ int x; int y; int z; } 现在让我们假设我希望将函数“展平”应用于这些点的列表,使其中一个变量变为0 其中扁平化可能类似于: flatten<variableName>(List<Point> points){ foreach(var point
point{
int x;
int y;
int z;
}
现在让我们假设我希望将函数“展平”应用于这些点的列表,使其中一个变量变为0
其中扁平化可能类似于:
flatten<variableName>(List<Point> points){
foreach(var point in points){
point.<variableName> = 0;
}
}
展平(列表点){
foreach(变量点到点){
点=0;
}
}
有人知道这在c#中是否可能,也许使用某种反射式结构?我知道它可以用Javascript实现,我希望用c#实现,因为它可以防止大量重复代码(注意,我想使用它的实际函数要大得多,并且包含多个子函数) 既然模拟代码希望有人传递变量名,为什么不直接传递lambda呢:
void Flatten(List<Point> points, Action<Point> action)
{
foreach(var point in points)
{
action(point);
}
}
如果要设置多个值,请传递表达式块:
Flatten(points, point =>
{
point.x = 0;
point.y = 0;
});
如果您对使用列表
(例如,哈希集)以外的序列感兴趣,则只需更改展平
即可使用IEnumerable
:
void Flatten(IEnumerable<Point> points, Action<Point> action)
{
foreach(var point in points)
{
action(point);
}
}
void展平(IEnumerable points,Action)
{
foreach(变量点到点)
{
行动(点);
}
}
既然模拟代码希望有人传递变量名,为什么不直接传递lambda呢:
void Flatten(List<Point> points, Action<Point> action)
{
foreach(var point in points)
{
action(point);
}
}
如果要设置多个值,请传递表达式块:
Flatten(points, point =>
{
point.x = 0;
point.y = 0;
});
如果您对使用列表
(例如,哈希集)以外的序列感兴趣,则只需更改展平
即可使用IEnumerable
:
void Flatten(IEnumerable<Point> points, Action<Point> action)
{
foreach(var point in points)
{
action(point);
}
}
void展平(IEnumerable points,Action)
{
foreach(变量点到点)
{
行动(点);
}
}
虽然我更喜欢肖恩的解决方案,因为它更接近C#并且不需要思考,但对于OP的确切问题,可能的回答是:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace StackOverflow
{
internal class Point
{
public int X { get; set; }
public int Y;
public int Z;
public override string ToString()
{
return $"({X}, {Y}, {Z})";
}
}
internal class Program
{
private static void Flatten(string name, IEnumerable<Point> points)
{
// Get either fields or properties
var memberInfo = typeof(Point)
.GetMembers()
.Where(m => m is FieldInfo || m is PropertyInfo)
.First(m => m.Name == name);
// Set target value
switch (memberInfo)
{
case FieldInfo fieldInfo:
foreach (var point in points) fieldInfo.SetValue(point, 0);
break;
case PropertyInfo propertyInfo:
foreach (var point in points) propertyInfo.SetValue(point, 0);
break;
}
}
private static void Main(string[] args)
{
var points = new List<Point>
{
new Point
{
X = 10,
Y = 20,
Z = 30
},
new Point
{
X = 100,
Y = 200,
Z = 300
}
};
Console.WriteLine($"BEFORE: {string.Join("; ", points)}");
Flatten(nameof(Point.X), points);
Console.WriteLine($"AFTER: {string.Join("; ", points)}");
Console.WriteLine("------------------");
Console.WriteLine($"BEFORE: {string.Join("; ", points)}");
Flatten(nameof(Point.Y), points);
Console.WriteLine($"AFTER: {string.Join("; ", points)}");
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
命名空间堆栈溢出
{
内部类点
{
公共整数X{get;set;}
公共智力;
公共INTZ;
公共重写字符串ToString()
{
返回$“({X},{Y},{Z})”;
}
}
内部课程计划
{
私有静态空白展平(字符串名称,IEnumerable点)
{
//获取字段或属性
var memberInfo=typeof(点)
.GetMembers()
.式中(m=>m为字段信息| | m为属性信息)
.First(m=>m.Name==Name);
//设定目标值
交换机(memberInfo)
{
案例字段信息字段信息:
foreach(点中的变量点)fieldInfo.SetValue(点,0);
打破
案例属性信息属性信息:
foreach(点中的var point)propertyInfo.SetValue(点,0);
打破
}
}
私有静态void Main(字符串[]args)
{
变量点=新列表
{
新点
{
X=10,
Y=20,
Z=30
},
新点
{
X=100,
Y=200,
Z=300
}
};
Console.WriteLine($”在:{string.Join(;“,points)}之前);
展平(点X的名称),点;
Console.WriteLine($”在:{string.Join(;“,points)}之后);
Console.WriteLine(“------------------------”;
Console.WriteLine($”在:{string.Join(;“,points)}之前);
展平(点的名称,Y),点);
Console.WriteLine($”在:{string.Join(;“,points)}之后);
}
}
}
输出:
之前:(10、20、30);(100200300)
之后:(0,20,30);(0200300)
前:(0,20,30);(0200300) 之后:(0,0,30);(0,0300) 编辑:
改进了处理字段和属性的代码。虽然我更喜欢Sean的解决方案,因为它更接近C#,并且不需要反射,但对于OP的确切问题,可能的回答是:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace StackOverflow
{
internal class Point
{
public int X { get; set; }
public int Y;
public int Z;
public override string ToString()
{
return $"({X}, {Y}, {Z})";
}
}
internal class Program
{
private static void Flatten(string name, IEnumerable<Point> points)
{
// Get either fields or properties
var memberInfo = typeof(Point)
.GetMembers()
.Where(m => m is FieldInfo || m is PropertyInfo)
.First(m => m.Name == name);
// Set target value
switch (memberInfo)
{
case FieldInfo fieldInfo:
foreach (var point in points) fieldInfo.SetValue(point, 0);
break;
case PropertyInfo propertyInfo:
foreach (var point in points) propertyInfo.SetValue(point, 0);
break;
}
}
private static void Main(string[] args)
{
var points = new List<Point>
{
new Point
{
X = 10,
Y = 20,
Z = 30
},
new Point
{
X = 100,
Y = 200,
Z = 300
}
};
Console.WriteLine($"BEFORE: {string.Join("; ", points)}");
Flatten(nameof(Point.X), points);
Console.WriteLine($"AFTER: {string.Join("; ", points)}");
Console.WriteLine("------------------");
Console.WriteLine($"BEFORE: {string.Join("; ", points)}");
Flatten(nameof(Point.Y), points);
Console.WriteLine($"AFTER: {string.Join("; ", points)}");
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
命名空间堆栈溢出
{
内部类点
{
公共整数X{get;set;}
公共智力;
公共INTZ;
公共重写字符串ToString()
{
返回$“({X},{Y},{Z})”;
}
}
内部课程计划
{
私有静态空白展平(字符串名称,IEnumerable点)
{
//获取字段或属性
var memberInfo=typeof(点)
.GetMembers()
.式中(m=>m为字段信息| | m为属性信息)
.First(m=>m.Name==Name);
//设定目标值
交换机(memberInfo)
{
案例字段信息字段信息:
foreach(点中的变量点)fieldInfo.SetValue(点,0);
打破
案例属性信息属性信息:
foreach(点中的var point)propertyInfo.SetValue(点,0);
打破
}
}
私有静态void Main(字符串[]args)
{
变量点=新列表
{
新点
{
X=10,
Y=20,
Z=30
},
新点
{
X=100,
Y=200,
Z=300