.net 将方法参数设置为只读

8nuwlpux  于 2023-07-01  发布在  .NET
关注(0)|答案(5)|浏览(177)

如何创建具有只读对象参数的方法?

public class Person
{
    public string Name;
}

public void RunMe(Person p)
{
    p.Name = "XXXX";
}

var p = new Person();
p.Name = "YYYY";
RunMe(p);
Console.WriteLine(p.Name); // "XXXX"

上面的代码导致此人的姓名为“XXXX”。我想阻止RunMe方法更改person的属性。

wyyhbhjk

wyyhbhjk1#

您可以使用接口来限制访问。传递接口而不是具体对象作为方法的参数也更好。

public interface IReadablePerson
{
    string Name { get; }
}

public interface IWritablePerson
{
    string Name { set; }
}

public class Person : IReadablePerson, IWritablePerson
{
    public string Name { get; set; }
}

然后用这样的方法

public void RunMe(IReadablePerson p)
{
   p.Name = "XXXX"; //compile time error!!!
}
bvjxkvbb

bvjxkvbb2#

方法是通过getset访问器,只是不要定义集合:

public String Name { get; }

这将创建一个属性,您可以将其完全视为用于您的目的的普通字段。下面的属性稍微复杂一点,使用方法来设置一个backing字段,您可以在msdn上了解到
如果你只需要设置一次属性,那么将set定义为private,并将参数传递给构造函数:

public class Person
{
  public Person(String name)
  {
     this.Name = name;
  }

  public String Name { get; private set; }
}
mzaanser

mzaanser3#

您似乎希望以某种方式锁定该成员。一个选项是使“set”依赖于另一个成员,如下所示:

public class Name
{
    public bool Locked { get; set; }

    private string name;
    public string Name
    {
        get { return this.name; }
        set
        {
            if(!this.Locked)
                this.name = val;
        }
    }
}

编辑:使锁永久化的另一种方法。

public class Person
{
    private bool locked = false;
    public void Lock()
    {
        this.locked = true;
    }
    public bool Locked
    {
        get { return this.locked; }
    }
    // add same Name member as above
}

编辑:还有一种锁的方法,用钥匙。

private object key = null;

public bool Locked
{ get { return this.key != null; } }

public void Lock(object obj)
{
    if (this.key == null)
    {
        this.key = obj;
    }
}

public void Unlock(object obj)
{
    if (this.key == obj)
    {
        this.key = null;
    }
}

如果尝试使用错误的密钥对象进行解锁,您可以根据需要抛出异常。

3pvhb19x

3pvhb19x4#

第一次设置属性后描述的行为如下:

private string _name;
public string Name 
{
    get { return _name; }
    set { // no setting }
}

这不是一个好的做法。你为属性创建了意外的行为(如果这是一个公共类)。任何消费程序集都不能查看get和set方法的主体,因此会期望set方法以某种方式(设置值)运行。
这种行为应该放在一个单独的集合方法中。通过这种方式,您可以查看它是否更改,如果需要,可以抛出异常,或者如果更改,则返回true。然后,您仍然可以使用属性来获取值。

private bool _locked;
public string Name { get; private set;}
public boolSetName(string value)
{
    bool hasChanged = false;
    if(!_locked)
    {
        Name = value;
        _locked = true;
        hasChanged = true;
    }
    return hasChanged
}
vtwuwzda

vtwuwzda5#

C#中的类是引用类型,所以如果Personclass,就没有办法做你想做的事情。
您可以将其设置为值类型(通过将其设置为struct),在这种情况下,将传入对象的副本,但这可能会影响程序中的其他一些点,因此如果您这样做,请谨慎。

相关问题