如何在c#中使局部字符串变量为只读

本文关键字:字符串 变量 只读 使局 | 更新日期: 2023-09-27 18:15:33

我有一个本地字符串(文件路径),我需要从一个函数检索只有一次,我想确保它永远不会再修改。我不能使用const关键字,因为我的字符串的值是在运行时而不是编译时确定的。所以我尝试使用readonly关键字代替,但Visual Studio告诉我,这是无效的我的项目。我怎样才能达到我想要的保护水平,最好是不创建另一个职业?

为了简单和公司政策,我已经(大幅度)缩减并重命名了我的类和函数,但概念是一样的。

public class myClass
{
    private void myFunction()
    {
      readonly string filePath = HelperClass.getFilePath("123");
     //do stuff
    }
}
public static class HelperClass
{ 
    public static string getFilePath(string ID)
    {
        switch(ID)
        {
             case "123":
                 return "C:/123.txt";
             case "234":
                 return "C:/234.txt";
             default:
                 throw new Exception(ID + " is not supported");
        }
    }
}

=== Edit For PS2Goat ====

public class myClass
{
    protected SomeObject o;
    private virtual readonly string path;        
    public myClass(someObject o)
    {
        this.o = o;
        path = HelperClass.getFilePath(o.getID());
    }
    private virtual void myFunction()
    { 
     //do stuff
    }
}
public class myDerivedClass
{
    private override virtual readonly string path;        
    public myDerivedClass(someObject o) : base(o)
    {
        path = HelperClass.getFilePath(o.getID()); //ID will be different
    }
    private override void myFunction()
    { 
     //do different stuff
    }
}


public static class HelperClass
{ 
    public static string getFilePath(string ID)
    {
        switch(ID)
        {
             case "123":
                 return "C:/123.txt";
             case "234":
                 return "C:/234.txt";
             default:
                 throw new Exception(ID + " is not supported");
        }
    }
}

看,所以我遇到的问题是,如果我想抛出一个异常,我现在必须在父类的构造函数中捕获它(直到该类被支持),因为父构造函数将在派生构造函数之前被调用。因此,在调用子构造函数(具有正确ID)之前,会设置一次错误的ID。

如何在c#中使局部字符串变量为只读

不能在方法中设置只读变量的作用域。因此,应将其提升为readonly static字段:

public class myClass
{
    private readonly static string filePath = HelperClass.getFilePath("123");
    private void myFunction()
    {    
      //do stuff
    }
}

这将导致您的filePath变量在第一次访问myClass时被初始化。如果这不是你想要的,getFilePath是一个长时间运行/昂贵的操作,你想等到myFunction被调用,你可以用System.Lazy<T>代替实现:

public class myClass
{
    private readonly static Lazy<string> filePath 
            = new Lazy<string>(() => HelperClass.getFilePath("123")));
    private void myFunction()
    {   
      string path = filePath.Value;
      //do stuff
    }
}

readonly意味着只能在类的构造函数或实例化中设置。所以,你可以把你的逻辑改成这样:

public class myClass
{
    private readonly string _filePath;
    public myClass()
    {
        _filePath = HelperClass.getFilePath("123");
    }
    private void myFunction()
    {
      // Use your _filePath here...
     //do stuff
    }
}
public static class HelperClass
{ 
    public static string getFilePath(string ID)
    {
        switch(ID)
        {
             case "123":
                 return "C:/123.txt";
             case "234":
                 return "C:/234.txt";
             default:
                 throw new Exception(ID + " is not supported");
        }
    }
}

您可以将要声明的readonly变量移到函数定义之外。

public class myClass
    {
        readonly string filePath = HelperClass.getFilePath("123");
        private void myFunction()
        {
         //do stuff with filePath
        }
    }

由于这是一个变量,而不是字段或属性,因此不能将其标记为只读。然而,你可以"欺骗"并通过使用匿名类型来实现你想要的,这确保了它的属性是只读的。

例如:

    var data = new
    {
        FileName = HelperClass.getFilePath("123");
    };

filePath变量提升到字段,这应该可以修复错误。局部变量不能是只读的

public class myClass
{
      readonly string filePath = HelperClass.getFilePath("123");
}