【问题标题】:Creating a list composed of object property references创建由对象属性引用组成的列表
【发布时间】:2019-09-06 12:02:18
【问题描述】:

我正在尝试做以下事情:
- 从第一种方法中,我正在遍历一堆对象(相同类型)并将指向特定属性的指针提取到列表中
- 然后这个列表将在某个时间点被提供给我程序中其他地方的另一个方法,并且必须修改原始对象的所有属性(根据提供的列表)

换句话说,假设我们有以下类:

public class Something  
{  
    public SomeFlag = False;  
    public Something()  
    {  
    }  
}  

在系统的某个地方,我们将一个相关的对象列表组成了 List。
现在,我们要扫描这个列表并将所有标志提取到“List flags”中(通过引用?):

List<bool> flags = new List<bool>();
foreach (var stuff in List<Something>)
{
  flags.Add(stuff.SomeFlag);
}

最后,在其他地方,我想更新这些标志,但更新应该会影响原始对象:

public static void SetStates(List<bool> myList)
{
    // The flag should get set to true by reference in the original object
    myList.SomeFlag = True;
}

【问题讨论】:

  • 谢谢。我弄乱了'ref',但无处可去。不知道有没有提到它。我只是将一些属性提取到一个列表中,这些属性在修改时会影响原始对象。所以可能与如何编译这个列表有关。有什么想法吗?
  • 您需要对原始对象的引用。是什么阻止您循环遍历 List 并在需要时设置它们?那么为什么不能直接将 List 传入 SetStates 呢?
  • 这样做似乎不会影响原始对象。
  • 我不确定我是否理解。我认为 List 基本上是由原始对象组成的列表?因此,通过遍历它们并修改它们,您将修改原始对象。
  • 不,您正在从对象列表中编译属性列表 - 故事中有 2 个列表

标签: c# list object reference


【解决方案1】:

使用actions 可能是实现此目的的一种方法:

public class Something
{
    public bool SomeFlag { get; set; }
}

internal class Program
{
    private static void Main()
    {
        var somethings = new[] {new Something(), new Something()};

        var flags = new List<Action<bool>>();

        // create your list of 'pointers'
        foreach (var something in somethings)
        {
            flags.Add(x => something.SomeFlag = x);
        }

        // set them all to true
        foreach (var action in flags)
        {
            action(true);
        }

        // check the results
        foreach (var something in somethings)
        {
            Console.WriteLine(something.SomeFlag);
        }

        Console.WriteLine("press any key to exit...");
        Console.ReadLine();
    }
}

【讨论】:

    【解决方案2】:

    在 C# 中,您不能保存对属性值的引用(例如指向存储值的内存位置的指针)。您只能保存对包含此属性值的对象的引用。

    在您的var list = new List&lt;Something&gt;() 中,您可以存储这些对对象的引用。

    请注意,值类型是不可能的。如果Somethingstruct,而不是class,那么list 将包含对象的副本,而不是对象的引用。所以我的其余答案假设我们正在谈论class Something

    您可以定义属性更改行为并使用对象列表应用它。

    如果您在编译时已经知道需要哪些属性和值,则可以创建一个 lambda 并传递它。

    // Define the behavior and get the object list
    Action<Something> setter = o => o.Someflag = true;
    var objectList = new List<Something>();
    
    // Call your processing method later on
    SetProperties(objectList, setter);
    
    void SetProperties<T>(List<T> objects, Action<T> setter)
    {
        objects.ForEach(setter);
    }
    

    如果您在编译时不知道需要哪些属性和哪些值,那么事情就会变得更加复杂。您将需要使用反射来获取属性描述符并设置值。

    这是一个简化的例子:

    // Define the behavior and get the object list
    var objectList = new List<Something>();
    string propertyName = "SomeFlag";
    PropertyInfo pi = typeof(Something).GetProperty(propertyName);
    MethodInfo setter = pi.GetSetMethod();
    object value = true;
    
    // Call your processing method later on
    SetProperties(objectList, setter, value);
    
    void SetProperties<T>(List<T> objects, MethodInfo setter, object value)
    {
        var arguments = new object[] { value } ;
        objects.ForEach(o => setter.Invoke(o, arguments));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-08
      • 2021-11-06
      • 1970-01-01
      • 2014-10-17
      • 2019-04-23
      • 1970-01-01
      • 2012-03-13
      • 2014-09-24
      相关资源
      最近更新 更多