类属性 - 在Property为null时通过Extension方法填充

时间:2017-08-23 12:24:00

标签: c# extension-methods

我有:

public class NameClass
{
 public NameClass(){}
 string Name {get; set;}
 bool IsValid {get; set;}
}

public class Person
{
 public Person() {}
 public NameClass Name {get; set;}
}

扩展方法:

public static void FillIt(this NameClass c, string name)
{
 if (c == null)
 {
  c = new NameClass();
 }
 if (string.IsNullOrEmpty(name) == false)
 {
  c.IsValid = true;
 }
 c.Name = name;
}

然后创建Person实例的空格:

private void CreateMyPerson()
{
 Person p = new Person();
 p.Name.FillIt(txtName.Text);

 if (p.Name == null) Response.Write("Ooops, PROBLEM!");
 // checking for filled p.Name - IT IS STILL null - WHY?
}
谷歌搜索没有帮助我,我不是母语为英语的人,也许我不能很好地问谷歌叔叔。

使用扩展方法来填充属性在我看来是分配值的最优雅方式,但虽然在扩展方法中" c"变量似乎被初始化并设置正常,稍后在检查p.Name是否为null时 - 它变为未设置 ...

任何线索?

3 个答案:

答案 0 :(得分:3)

执行此操作时:

c = new NameClass();

您未在NameClass对象的属性中分配Person的实例。您将分配给本地变量c 。完成该分配后,该局部变量不再与Person类上的属性引用有任何关系。

如果您始终要初始化Name,请在Person构造函数中执行此操作:

public Person()
{
    this.Name = new NameClass();
}

然后你的扩展方法首先不需要检查null:

public static void FillIt(this NameClass c, string name)
{
    if (string.IsNullOrEmpty(name) == false)
    {
        c.IsValid = true;
    }
    c.Name = name;
}

由于此版本中永远不会重新分配c,因此它仍然指向Person对象上的属性。

虽然取决于你在这里尝试完成的任务,你甚至还需要这种扩展方法吗?如果 Person有一个名称,您可以在Person构造函数上要求它。和/或NameClass构造函数。

初始化一个对象,然后检查它是否有效是两个步骤,但要求它在初始化时有效,只需一步即可。如果"无效"不应该允许对象,只是不允许它。

答案 1 :(得分:2)

p.Name是一个引用类型变量,指向null。调用FillIt方法会将p.Namenull)的值复制到引用变量c。因此,事实上变量cp.Name之间没有任何联系,变量c上的任何操作都是本地的。

另一方面,如果p.Name不是null并且引用内存地址,请说0x1111,那么调用扩展方法会将该地址复制到变量c c上的操作也会影响p.Name,因为它们都引用相同的内存地址。

答案 2 :(得分:0)

正如其他人所说,为什么它不起作用,我想给你一个替代方案。

基本上你需要类似的东西:

public static void FillIt(this out NameClass c, string name)

但这无效。

替代方案可以是:

public static NameClass FillIt(this NameClass c, string name)
{
    if (c == null)
        c = new NameClass();

    if (string.IsNullOrEmpty(name) == false)
        c.IsValid = true;

    c.Name = name;

    //note: return the object c
    return c;
}

并称之为:

Person p = new Person();
//note: set the p.Name
p.Name = p.Name.FillIt(txtName.Text);

你也可以这样做,虽然我不建议同时使用XD:

(p.Name ?? new NameClass()).FillIt(txtName.Text);