静态索引器?
为什么 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];
}
}
上面的代码将从静态索引器中受益匪浅。 但是它不会编译,因为不允许使用静态索引器。 为什么会这样呢?
Why are static indexers disallowed in C#? I see no reason why they should not be allowed and furthermore they could be very useful.
For example:
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];
}
}
The above code would benefit greatly from a static indexer. However it won't compile because static indexers are not allowed. Why is this so?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我相信它被认为不是很有用。 我认为这也很遗憾 - 我倾向于使用的一个例子是 Encoding,其中
Encoding.GetEncoding("foo")
可能是Encoding["Foo"]
。 我不认为它会经常出现,但除了其他任何事情之外,不可用只是感觉有点不一致。我必须检查一下,但我怀疑它已经在 IL(中间语言)中可用。
I believe it was considered not to be terribly useful. I think it's a shame too - an example I tend to use is Encoding, where
Encoding.GetEncoding("foo")
could beEncoding["Foo"]
. I don't think it would come up very often, but aside from anything else it just feels a little inconsistent not to be available.I would have to check, but I suspect it's available in IL (Intermediate Language) already.
索引器表示法需要引用
this
。 由于静态方法没有对该类的任何特定实例的引用,因此您不能将this
与它们一起使用,因此您不能在静态方法上使用索引器表示法。问题的解决方案是使用单例模式,如下所示:
现在您可以使用索引器表示法调用
Utilities.ConfigurationManager["someKey"]
。Indexer notation requires a reference to
this
. Since static methods don't have a reference to any particular instance of the class, you can't usethis
with them, and consequently you can't use indexer notation on static methods.The solution to your problem is using a singleton pattern as follows:
Now you can call
Utilities.ConfigurationManager["someKey"]
using indexer notation.作为解决方法,您可以在单例/静态对象上定义实例索引器(假设 ConfigurationManager 是单例,而不是静态类):
As a work-around, you can define an instance indexer on a singleton/static object (say that ConfigurationManager is a singleton, instead of being a static class):
我还需要(嗯,更像是最好的)一个静态索引器来存储属性,所以我想出了一个有点尴尬的解决方法:
在您想要有一个静态索引器的类中(此处:Element),创建同名+“Dict”的子类。 给它一个只读静态作为所述子类的实例,然后添加所需的索引器。
最后,将类添加为静态导入(因此子类仅公开静态字段)。
然后你可以使用它大写作为类型,或者不使用字典:
但是,唉,如果一个人实际上使用对象作为“值”类型,那么下面的内容会更短(至少作为声明),并且还提供立即类型转换:
I was also in need (well, more like nice-to-have) of an static indexer to store attributes, so I figured out a somewhat awkward workaround:
Within the class you want to have an static indexer (here: Element), create a subclass of the same name + "Dict". Give it a readonly static as instance of said subclass, and then add your desired indexer.
Last, add the class as static import (hence the subclass to only expose the static field).
and then you can use it either capitalized as Type, or without as dictionary:
But alas, if one were to actually use object as "value"-Type, then the below would be still shorter (at least as declaration), and also provide immediate Typecasting:
使用 C# 6 中较新的构造,您可以使用属性表达式主体来简化单例模式。
例如,我使用了以下与 code-lense 配合良好的快捷方式:
它具有可查找替换的额外好处,可以升级旧代码并统一应用程序设置访问权限。
With the newer constructs in C# 6, you might simplify the singleton pattern with a property expression body.
For instance, I used the following shortcut which works nicely with code-lense:
It has the added benefit of being find-replace-able for upgrading older code and unifying your application settings access.
this 关键字引用该类的当前实例。 静态成员函数没有 this 指针。 this 关键字可用于从构造函数、实例方法和实例访问器中访问成员。(检索自 msdn)。 由于这引用了类的实例,因此它与静态的本质相冲突,因为静态与类的实例无关。
一种解决方法如下,它允许您对私有索引使用索引器
字典,因此您只需要创建一个新实例并访问静态部分。
这允许您跳过访问类成员的整个过程,而只需创建它的实例并为其建立索引。
The this keyword refers to the current instance of the class. Static member functions do not have a this pointer. The this keyword can be used to access members from within constructors, instance methods, and instance accessors.(retrieved from msdn). Since this references an instance of the class it conflicts with the nature of static, since static isn't associated with an instance of the class.
One workaround would be the following which allows you to use the indexer against a private
Dictionary so you only need to create a new instance and you access the static part.
This allows you to skip the whole accessing a member of the class and just create an instance of it and index it.
原因是因为很难理解静态索引器到底在索引什么。
您说代码会受益于静态索引器,但真的会吗? 它所做的就是将 this: 更改
为 this: ,
这不会以任何方式使代码变得更好; 它并没有减少很多行代码,由于自动完成功能,编写起来并不容易,而且不太清楚,因为它隐藏了您正在获取和设置称为“属性”的东西的事实,并且实际上迫使读者请阅读有关索引器返回或设置的确切内容的文档,因为它绝对不是您要为其建立索引的属性,而同时使用两者:
您可以大声朗读它并立即了解代码的作用。
请记住,我们希望编写易于(=快速)理解的代码,而不是编写速度快的代码。 不要将编写代码的速度与完成项目的速度混淆。
The reason is because it is quite hard to understand what exactly you are indexing with a static indexer.
You say that the code would benefit from a static indexer, but would it really? All it would do is change this:
Into this:
which does not make the code better in any way; it is not smaller by many lines of code, it isn't easier to write thanks to autocomplete and it is less clear, as it hides the fact that you are getting and setting something you call 'Property' and it actually forces the reader to go read the documentation on what exactly the indexer returns or sets, because it is in no way obvious that it is a property that you are indexing for, while with both:
You can read it out loud and immediately understand what the code does.
Remember that we want to write code that is easy (= fast) to understand, not code that is fast to write. Do not mistake the speed at which you can lay down the code with the speed at which you complete projects.