Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中将属性本身作为参数传递给函数#_C#_Properties_Parameter Passing - Fatal编程技术网

C# 在C中将属性本身作为参数传递给函数#

C# 在C中将属性本身作为参数传递给函数#,c#,properties,parameter-passing,C#,Properties,Parameter Passing,我正在寻找一种方法来将属性本身传递给函数。不是财产的价值。函数事先不知道将使用哪个属性进行排序。本例中最简单的方法是:使用不同的参数类型创建4个覆盖。另一种方法是在函数内部使用typeof()。当Class1有数百个属性时,这两种方法都是不可接受的。到目前为止,我发现了以下方法: class Class1 { string vehName; int maxSpeed; int fuelCapacity; bool isFlying; } class Proces

我正在寻找一种方法来将属性本身传递给函数。不是财产的价值。函数事先不知道将使用哪个属性进行排序。本例中最简单的方法是:使用不同的参数类型创建4个覆盖。另一种方法是在函数内部使用
typeof()。当Class1有数百个属性时,这两种方法都是不可接受的。到目前为止,我发现了以下方法:

class Class1
{
    string vehName;
    int maxSpeed;
    int fuelCapacity;
    bool isFlying;
}

class Processor
{
    List<Class1> vehicles = null;
    Processor(List<Class1> input)
    {
        vehicles = input;
    }

    List<Class1> sortBy(List<Class1> toSort, string propName)
    {
        if (toSort != null && toSort.Count > 0)
        {
            return toSort.OrderBy(x => typeof(Class1).GetProperty(propName).GetValue(x, null)).ToList();
        }
        else return null;
    }
}

class OuterUser
{
    List<Class1> vehicles = new List<Class1>();
    // ... fill the list
    Processor pr = new Processor(vehicles);
    List<Class1> sorted = pr.sortBy("maxSpeed");
}

你为什么不使用Linq呢?比如:

vehicles.OrderBy(v => v.maxSpeed).ToList();

可以将属性访问器传递给该方法

List<Class1> SortBy(List<Class1> toSort, Func<Class1, IComparable> getProp)
{
    if (toSort != null && toSort.Count > 0) {
        return toSort
            .OrderBy(x => getProp(x))
            .ToList();
    }
    return null;
}

但您可以更进一步,编写自己的扩展方法

public static class CollectionExtensions
{
    public static List<TSource> OrderByAsListOrNull<TSource, TKey>(
        this ICollection<TSource> collection, Func<TSource,TKey> keySelector)

        if (collection != null && collection.Count > 0) {
            return collection
                .OrderBy(x => keySelector(x))
                .ToList();
        }
        return null;
    }
}

其中
T
是属性的类型。

可以使用lambda表达式传递属性信息:

void DoSomething<T>(Expression<Func<T>> property)
{
    var propertyInfo = ((MemberExpression)property.Body).Member as PropertyInfo;
    if (propertyInfo == null)
    {
        throw new ArgumentException("The lambda expression 'property' should point to a valid Property");
    }
}

从上面的答案中再加上一句。您还可以为订单方向做一个简单的标记

public class Processor
{
    public List<SortableItem> SortableItems { get; set; }

    public Processor()
    {
        SortableItems = new List<SortableItem>();
        SortableItems.Add(new SortableItem { PropA = "b" });
        SortableItems.Add(new SortableItem { PropA = "a" });
        SortableItems.Add(new SortableItem { PropA = "c" });
    }

    public void SortItems(Func<SortableItem, IComparable> keySelector, bool isAscending)
    {
        if(isAscending)
            SortableItems = SortableItems.OrderBy(keySelector).ToList();
        else
            SortableItems = SortableItems.OrderByDescending(keySelector).ToList();
    }
}
公共类处理器
{
公共列表可排序项{get;set;}
公共处理器()
{
SortableItems=新列表();
添加(新的SortableItem{PropA=“b”});
添加(新的SortableItem{PropA=“a”});
添加(新的SortableItem{PropA=“c”});
}
公共无效的SortItems(Func keySelector,bool isAscending)
{
如果(正在搜索)
SortableItems=SortableItems.OrderBy(keySelector.ToList();
其他的
SortableItems=SortableItems.OrderByDescending(keySelector.ToList();
}
}

我发现@MatthiasG的答案中缺少的是如何获取属性值,而不仅仅是它的名称

public static string Meth<T>(Expression<Func<T>> expression)
{
    var name = ((MemberExpression)expression.Body).Member.Name;
    var value = expression.Compile()();
    return string.Format("{0} - {1}", name, value);
}

这里有很好的解决方案

void GetString(字符串输入、T目标、表达式outExpr)
{
如果(!string.IsNullOrEmpty(输入))
{
var expr=(MemberExpression)outExpr.Body;
var prop=(PropertyInfo)expr.Member;
属性设置值(目标、输入、空);
}
}
void Main()
{
var person=新的person();
GetString(“test”,person,x=>x.Name);
Assert(person.Name==“test”);
}

我想给出一个简单易懂的答案

函数的参数是:
System.Func

我们像这样传递属性:
Function(x=>x.Property)

代码如下:

class HDNData
{
    private int m_myInt;
    
    public int MyInt
    {
        get { return m_myInt; }
    }
    
    public void ChangeHDNData()
    {
        if (m_myInt == 0)
            m_myInt = 69;
        else
            m_myInt = 0;
    }
}

static class HDNTest
{
    private static HDNData m_data = new HDNData();
    
    public static void ChangeHDNData()
    {
        m_data.ChangeHDNData();
    }
    
    public static void HDNPrint(System.Func<HDNData, int> dataProperty)
    {
        Console.WriteLine(dataProperty(m_data));//Print to console the dataProperty (type int) of m_data
    }
}

//******Usage******
HDNTest.ChangeHDNData();
//This is what you want: Pass property itself (which is MyInt) to function as parameter in C#
HDNTest.HDNPrint(x => x.MyInt);
hdnda类
{
私人密密特;
公共整数MyInt
{
获取{return m_myInt;}
}
公共无效更改数据()
{
如果(m_myInt==0)
m_myInt=69;
其他的
m_myInt=0;
}
}
静态类HDNTest
{
私有静态hdnda m_data=新hdnda();
公共静态无效更改数据()
{
m_data.changehdnata();
}
公共静态void HDNPrint(System.Func dataProperty)
{
Console.WriteLine(dataProperty(m_data));//打印以控制m_数据的dataProperty(type int)
}
}
//******用法******
HDNTest.changehdnata();
//这就是您想要的:传递属性本身(即MyInt)作为C中的参数#
HDNTest.HDNPrint(x=>x.MyInt);

首先如何选择用于排序的属性?其他类的可能副本将使用
处理器
。他们不应该看到
车辆
。另外,
sortBy
将有更多的逻辑(升序/降序/一些过滤)…然后我想你应该看看上面@olivier的答案,关于编写你自己的扩展方法(添加过滤等)。这个方法与LINQ的OrderBy有什么不同吗?@Chris Gessler:是的,如果源集合为
null
或其
Count
0
,则返回
null
,否则返回
列表。如果源为
null
,LINQ的
OrderBy
将抛出异常,否则返回
IEnumerable
。我不知道这个方法对其他人是否真的有用,但OP显然需要它。如果您需要获取有关属性的更多信息,例如属性名称,可以使用这种方法(在实现
INotifyPropertyChanged
时很有用)。但是,在这种情况下,这有点过分,因为返回属性值就足够了。
void ReadAndWriteProperty(Func<Class1, T> getProp, Action<Class1, T> setProp)
void DoSomething<T>(Expression<Func<T>> property)
{
    var propertyInfo = ((MemberExpression)property.Body).Member as PropertyInfo;
    if (propertyInfo == null)
    {
        throw new ArgumentException("The lambda expression 'property' should point to a valid Property");
    }
}
DoSomething(() => this.MyProperty);
public class Processor
{
    public List<SortableItem> SortableItems { get; set; }

    public Processor()
    {
        SortableItems = new List<SortableItem>();
        SortableItems.Add(new SortableItem { PropA = "b" });
        SortableItems.Add(new SortableItem { PropA = "a" });
        SortableItems.Add(new SortableItem { PropA = "c" });
    }

    public void SortItems(Func<SortableItem, IComparable> keySelector, bool isAscending)
    {
        if(isAscending)
            SortableItems = SortableItems.OrderBy(keySelector).ToList();
        else
            SortableItems = SortableItems.OrderByDescending(keySelector).ToList();
    }
}
public static string Meth<T>(Expression<Func<T>> expression)
{
    var name = ((MemberExpression)expression.Body).Member.Name;
    var value = expression.Compile()();
    return string.Format("{0} - {1}", name, value);
}
Meth(() => YourObject.Property);
void GetString<T>(string input, T target, Expression<Func<T, string>> outExpr)
{
    if (!string.IsNullOrEmpty(input))
    {
        var expr = (MemberExpression) outExpr.Body;
        var prop = (PropertyInfo) expr.Member;
        prop.SetValue(target, input, null);
    }
}

void Main()
{
    var person = new Person();
    GetString("test", person, x => x.Name);
    Debug.Assert(person.Name == "test");
}
class HDNData
{
    private int m_myInt;
    
    public int MyInt
    {
        get { return m_myInt; }
    }
    
    public void ChangeHDNData()
    {
        if (m_myInt == 0)
            m_myInt = 69;
        else
            m_myInt = 0;
    }
}

static class HDNTest
{
    private static HDNData m_data = new HDNData();
    
    public static void ChangeHDNData()
    {
        m_data.ChangeHDNData();
    }
    
    public static void HDNPrint(System.Func<HDNData, int> dataProperty)
    {
        Console.WriteLine(dataProperty(m_data));//Print to console the dataProperty (type int) of m_data
    }
}

//******Usage******
HDNTest.ChangeHDNData();
//This is what you want: Pass property itself (which is MyInt) to function as parameter in C#
HDNTest.HDNPrint(x => x.MyInt);