为什么C#中不允许使用静态索引器?我认为没有理由不允许他们这样做,而且他们可能非常有用。
例如:
public static class ConfigurationManager
{
public object this[string name]
{
get => ConfigurationManager.getProperty(name);
set => ConfigurationManager.editProperty(name, value);
}
/// <summary>
/// This will write the value to the property. Will overwrite if the property is already there
/// </summary>
/// <param name="name">Name of the property</param>
/// <param name="value">Value to be wrote (calls ToString)</param>
public static void editProperty(string name, object value)
{
var ds = new DataSet();
var configFile = new FileStream("./config.xml", FileMode.OpenOrCreate);
ds.ReadXml(configFile);
if (ds.Tables["config"] == null)
ds.Tables.Add("config");
var config = ds.Tables["config"];
if (config.Rows[0] == null)
config.Rows.Add(config.NewRow());
if (config.Columns[name] == null)
config.Columns.Add(name);
config.Rows[0][name] = value.ToString();
ds.WriteXml(configFile);
configFile.Close();
}
public static void addProperty(string name, object value) =>
ConfigurationManager.editProperty(name, value);
public static object getProperty(string name)
{
var ds = new DataSet();
var configFile = new FileStream("./config.xml", FileMode.OpenOrCreate);
ds.ReadXml(configFile);
configFile.Close();
if (ds.Tables["config"] == null) return null;
var config = ds.Tables["config"];
if (config.Rows[0] == null) return null;
if (config.Columns[name] == null) return null;
return config.Rows[0][name];
}
}
上面的代码将从静态索引器中受益匪浅。但是它不会编译,因为不允许使用静态索引器。为什么会这样?
答案 0 :(得分:86)
我认为它被认为不是非常有用。我认为这也是一种耻辱 - 我倾向于使用的一个例子是编码,其中Encoding.GetEncoding("foo")
可能是Encoding["Foo"]
。我认为它不会经常出现非常,但除了其他任何事情之外,它只是感觉有点不一致而无法使用。
我必须检查,但我怀疑它已经在IL(中级语言)中可用。
答案 1 :(得分:66)
索引器表示法需要引用this
。由于静态方法没有对类的特定实例的引用,因此不能将this
与它们一起使用,因此您不能在静态方法上使用索引符号。
问题的解决方案是使用单例模式,如下所示:
public class Utilities
{
private static ConfigurationManager _configurationManager = new ConfigurationManager();
public static ConfigurationManager ConfigurationManager => _configurationManager;
}
public class ConfigurationManager
{
public object this[string value]
{
get => new object();
set => // set something
}
}
现在,您可以使用索引符号来调用Utilities.ConfigurationManager["someKey"]
。
答案 2 :(得分:7)
作为解决方法,您可以在单例/静态对象上定义实例索引器(假设ConfigurationManager是单例,而不是静态类):
class ConfigurationManager
{
//private constructor
ConfigurationManager() {}
//singleton instance
public static ConfigurationManager singleton;
//indexer
object this[string name] { ... etc ... }
}
答案 3 :(得分:0)
使用C#6中的较新结构,您可以使用属性表达式主体简化单例模式。 例如,我使用了以下快捷方式,可以很好地与代码许可配合使用:
public static class Config
{
public static NameValueCollection Get => ConfigurationManager.AppSettings;
}
它的另一个好处是可查找替换,可以升级较旧的代码并统一您的应用程序设置访问权限。
答案 4 :(得分:0)
我还需要一个静态索引器来存储属性(更像是一个不错的东西),所以我想出了一个比较尴尬的解决方法:
在要具有静态索引器的类(此处为Element)中,创建一个同名+“ Dict”的子类。给它一个只读的static作为所述子类的实例,然后添加所需的索引器。
最后,将类添加为静态导入(因此子类仅显示静态字段)。
import static Element.ElementDict;
public class Element {
// ....
private static readonly Dictionary<string, object> elemDict = new Dictionary<string, object>();
public class ElementDict {
public readonly static ElementDict element = new ElementDict();
public object this[string key] {
get => elemDict.TryGetValue(key, out object o) ? o : null;
set => elemDict[key] = value;
}
}
}
,然后您可以将其大写为Type或不将其用作字典:
var cnt = element["counter"] as int;
element["counter"] = cnt;
但是,如果实际上是将对象用作“值” -Type,那么下面的内容将更短(至少作为声明),并且还提供立即的Typecasting:
public static T load<T>(string key) => elemDict.TryGetValue(key, out object o) ? (T) o : default(T);
public static void store<T>(string key, T value) => elemDict[key] = value;
var cnt = Element.load<int>("counter");
Element.store("counter", cnt);
答案 5 :(得分:-1)
原因是很难理解您使用静态索引器确切索引的内容。
你说代码会受益于静态索引器,但它会真的吗?它只会改变这一点:
ConfigurationManager.editProperty(name, value);
...
value = ConfigurationManager.getProperty(name)
进入这个:
ConfigurationManager[name] = value
...
value = ConfigurationManager[name]
不会以任何方式改善代码;许多代码行并不小,由于自动完成它并不容易编写,而且不太清楚,因为它隐藏了这样一个事实:你正在设置你所调用的东西&#39; Property&#39;它实际上迫使读者阅读关于索引器返回或设置的文档的文档,因为它并不是显而易见的,它是你正在索引的属性,而两者都是:
ConfigurationManager.editProperty(name, value);
...
value = ConfigurationManager.getProperty(name)
您可以大声朗读并立即了解代码的作用。
请记住,我们希望编写易于(=快速)理解的代码,而不是编写速度快的代码。不要错误地以您完成项目的速度来设置代码的速度。
答案 6 :(得分:-2)
this关键字引用类的当前实例。静态成员函数没有this指针。 this关键字可用于从构造函数,实例方法和实例访问器中访问成员。(从msdn检索)。由于这引用了类的实例,因此它与static的性质相冲突,因为static与类的实例没有关联。
以下一个解决方法是允许您对私有使用索引器 字典,因此您只需要创建一个新实例,然后访问静态部分。
public class ConfigurationManager
{
public ConfigurationManager()
{
// TODO: Complete member initialization
}
public object this[string keyName]
{
get
{
return ConfigurationManagerItems[keyName];
}
set
{
ConfigurationManagerItems[keyName] = value;
}
}
private static Dictionary<string, object> ConfigurationManagerItems = new Dictionary<string, object>();
}
这允许您跳过访问该类成员的整个过程,只需创建它的实例并将其编入索引。
new ConfigurationManager()["ItemName"]