设置不带反射的只读字符串
Setting ReadOnly Strings without Reflection
我正在开发一个需要访问 public 字符串的应用程序。
但是,我也希望限制写入权限。因为我有很多字符串,所以我想避免每个字符串都有 getter 和私有 setter。
查看下面的代码:
public readonly string privateMem, peakVM, peakPaged, pagedSysMem, pagedMem, nonpagedSysMem;
public override void Capture()
{
using (Process p = Process.GetCurrentProcess())
{
// Throws error as privateMem can't be assigned a value
privateMem = string.Format("{0:N0} K", p.PrivateMemorySize64 / 1024);
peakVM = string.Format("{0:N0} K", p.PeakVirtualMemorySize64 / 1024);
peakPaged = string.Format("{0:N0} K", p.PeakPagedMemorySize64 / 1024);
pagedSysMem = string.Format("{0:N0} K", p.PagedSystemMemorySize64 / 1024);
pagedMem = string.Format("{0:N0} K", p.PagedMemorySize64 / 1024);
nonpagedSysMem = string.Format("{0:N0} K", p.NonpagedSystemMemorySize64 / 1024);
}
}
我知道有一些方法可以通过反射为只读字段赋值,但是我从其他几个 Whosebug 问题中了解到这是一个糟糕的想法。
总之:
1。
如何在不进行反射的情况下为只读字符串赋值,或者在不使用冗长的 getters 和 setters 的情况下是否存在更好的解决方案?
2。
有没有办法声明一个变量,给它赋值,然后指定它为只读?
你想做的事毫无意义。只读字段只能在构造函数中填充。它们对于依赖注入非常有用,例如,事物仅在构造函数内部设置,仅此而已,无法在其外部进行修改。
例如,您始终可以使用私有集。说 getter 和 setters 是 "verbose" 也没有意义。他们在那里是有原因的。试图找到一种以不同方式做事的方法很可能意味着疯狂的代码,而所有这些只是为了避免使用简单的 setter?
想想你在做什么以及为什么,然后最后问问自己,这真的值得吗?
public string privateMem { get; private set; }
public string peakVM { get; private set; }
public string peakPaged { get; private set; }
public string pagedSysMem { get; private set; }
public string pagedMem { get; private set; }
public string nonpagedSysMem { get; private set; }
这花了大约 20 秒。这有什么啰嗦的?
最后我只用了一本字典。这样我只需要一个 getter 和一个私有的 setter,而且以后添加更多 strings/system 信息时它的可扩展性要好得多。
public Dictionary<string, string> memoryStrings
{
get;
private set;
}
public MemoryUsageFragment() {
memoryStrings = new Dictionary<string, string>();
}
public override void Capture()
{
using (Process p = Process.GetCurrentProcess())
{
memoryStrings.Add("privateMem", string.Format("{0:N0} K", p.PrivateMemorySize64 / 1024));
memoryStrings.Add("peakVm", string.Format("{0:N0} K", p.PeakVirtualMemorySize64 / 1024));
memoryStrings.Add("peakPaged", string.Format("{0:N0} K", p.PeakPagedMemorySize64 / 1024));
memoryStrings.Add("pagedSysMem", string.Format("{0:N0} K", p.PagedSystemMemorySize64 / 1024));
memoryStrings.Add("pagedMem", string.Format("{0:N0} K", p.PagedMemorySize64 / 1024));
memoryStrings.Add("nonpagedSysMem", string.Format("{0:N0} K", p.NonpagedSystemMemorySize64 / 1024));
}
}
您当前使用字典的答案是不正确的,因为它不是只读的。
更正确的方法是基于字典初始化一个 IReadOnlyDictionary
(在 .NET 4.5 或更高版本中)实例一次,并添加逻辑以防止它在初始化后被新值覆盖。
通过使用支持字段,我们可以确保即使在 class 内部尝试修改它,一旦它包含值就不会被覆盖。
private IReadOnlyDictionary<string, string> _memoryStrings;
public IReadOnlyDictionary<string, string> memoryStrings
{
get
{
return _memoryStrings;
}
private set
{
if (_memoryStrings != null && _memoryStrings.Count() > 0) return;
_memoryStrings = value;
}
}
public void Capture()
{
if (memoryStrings == null || memoryStrings.Count() == 0)
{
using (Process p = Process.GetCurrentProcess())
{
memoryStrings = new Dictionary<string, string>
{
{"privateMem", string.Format("{0:N0} K", p.PrivateMemorySize64 / 1024)},
{"peakVm", string.Format("{0:N0} K", p.PeakVirtualMemorySize64 / 1024)},
{"peakPaged", string.Format("{0:N0} K", p.PeakPagedMemorySize64 / 1024)},
{"pagedSysMem", string.Format("{0:N0} K", p.PagedSystemMemorySize64 / 1024)},
{"pagedMem", string.Format("{0:N0} K", p.PagedMemorySize64 / 1024)},
{ "nonpagedSysMem", string.Format("{0:N0} K", p.NonpagedSystemMemorySize64 / 1024)}
};
}
}
}
这给了我们多层次的不变性。
如果您多次调用 Capture()
,它只会 运行 第一次计算。
如果您试图覆盖 class 中别处的字典,一旦它包含值就不会被覆盖。
如果您在创建集合后尝试覆盖 属性 或添加一个值,您将收到编译时异常(在使用索引器或尝试使用 .Add()
方法)或 运行 时间异常(在通过强制转换为 IDictionary
使用 .Add()
方法的情况下)。
我正在开发一个需要访问 public 字符串的应用程序。 但是,我也希望限制写入权限。因为我有很多字符串,所以我想避免每个字符串都有 getter 和私有 setter。
查看下面的代码:
public readonly string privateMem, peakVM, peakPaged, pagedSysMem, pagedMem, nonpagedSysMem;
public override void Capture()
{
using (Process p = Process.GetCurrentProcess())
{
// Throws error as privateMem can't be assigned a value
privateMem = string.Format("{0:N0} K", p.PrivateMemorySize64 / 1024);
peakVM = string.Format("{0:N0} K", p.PeakVirtualMemorySize64 / 1024);
peakPaged = string.Format("{0:N0} K", p.PeakPagedMemorySize64 / 1024);
pagedSysMem = string.Format("{0:N0} K", p.PagedSystemMemorySize64 / 1024);
pagedMem = string.Format("{0:N0} K", p.PagedMemorySize64 / 1024);
nonpagedSysMem = string.Format("{0:N0} K", p.NonpagedSystemMemorySize64 / 1024);
}
}
我知道有一些方法可以通过反射为只读字段赋值,但是我从其他几个 Whosebug 问题中了解到这是一个糟糕的想法。
总之:
1。 如何在不进行反射的情况下为只读字符串赋值,或者在不使用冗长的 getters 和 setters 的情况下是否存在更好的解决方案?
2。 有没有办法声明一个变量,给它赋值,然后指定它为只读?
你想做的事毫无意义。只读字段只能在构造函数中填充。它们对于依赖注入非常有用,例如,事物仅在构造函数内部设置,仅此而已,无法在其外部进行修改。
例如,您始终可以使用私有集。说 getter 和 setters 是 "verbose" 也没有意义。他们在那里是有原因的。试图找到一种以不同方式做事的方法很可能意味着疯狂的代码,而所有这些只是为了避免使用简单的 setter?
想想你在做什么以及为什么,然后最后问问自己,这真的值得吗?
public string privateMem { get; private set; }
public string peakVM { get; private set; }
public string peakPaged { get; private set; }
public string pagedSysMem { get; private set; }
public string pagedMem { get; private set; }
public string nonpagedSysMem { get; private set; }
这花了大约 20 秒。这有什么啰嗦的?
最后我只用了一本字典。这样我只需要一个 getter 和一个私有的 setter,而且以后添加更多 strings/system 信息时它的可扩展性要好得多。
public Dictionary<string, string> memoryStrings
{
get;
private set;
}
public MemoryUsageFragment() {
memoryStrings = new Dictionary<string, string>();
}
public override void Capture()
{
using (Process p = Process.GetCurrentProcess())
{
memoryStrings.Add("privateMem", string.Format("{0:N0} K", p.PrivateMemorySize64 / 1024));
memoryStrings.Add("peakVm", string.Format("{0:N0} K", p.PeakVirtualMemorySize64 / 1024));
memoryStrings.Add("peakPaged", string.Format("{0:N0} K", p.PeakPagedMemorySize64 / 1024));
memoryStrings.Add("pagedSysMem", string.Format("{0:N0} K", p.PagedSystemMemorySize64 / 1024));
memoryStrings.Add("pagedMem", string.Format("{0:N0} K", p.PagedMemorySize64 / 1024));
memoryStrings.Add("nonpagedSysMem", string.Format("{0:N0} K", p.NonpagedSystemMemorySize64 / 1024));
}
}
您当前使用字典的答案是不正确的,因为它不是只读的。
更正确的方法是基于字典初始化一个 IReadOnlyDictionary
(在 .NET 4.5 或更高版本中)实例一次,并添加逻辑以防止它在初始化后被新值覆盖。
通过使用支持字段,我们可以确保即使在 class 内部尝试修改它,一旦它包含值就不会被覆盖。
private IReadOnlyDictionary<string, string> _memoryStrings;
public IReadOnlyDictionary<string, string> memoryStrings
{
get
{
return _memoryStrings;
}
private set
{
if (_memoryStrings != null && _memoryStrings.Count() > 0) return;
_memoryStrings = value;
}
}
public void Capture()
{
if (memoryStrings == null || memoryStrings.Count() == 0)
{
using (Process p = Process.GetCurrentProcess())
{
memoryStrings = new Dictionary<string, string>
{
{"privateMem", string.Format("{0:N0} K", p.PrivateMemorySize64 / 1024)},
{"peakVm", string.Format("{0:N0} K", p.PeakVirtualMemorySize64 / 1024)},
{"peakPaged", string.Format("{0:N0} K", p.PeakPagedMemorySize64 / 1024)},
{"pagedSysMem", string.Format("{0:N0} K", p.PagedSystemMemorySize64 / 1024)},
{"pagedMem", string.Format("{0:N0} K", p.PagedMemorySize64 / 1024)},
{ "nonpagedSysMem", string.Format("{0:N0} K", p.NonpagedSystemMemorySize64 / 1024)}
};
}
}
}
这给了我们多层次的不变性。
如果您多次调用 Capture()
,它只会 运行 第一次计算。
如果您试图覆盖 class 中别处的字典,一旦它包含值就不会被覆盖。
如果您在创建集合后尝试覆盖 属性 或添加一个值,您将收到编译时异常(在使用索引器或尝试使用 .Add()
方法)或 运行 时间异常(在通过强制转换为 IDictionary
使用 .Add()
方法的情况下)。