简体   繁体   English

我是否以正确的方式使用静电?

[英]Am I using static in the right way?

I'm writing an XNA engine and I am storing all of the models in a List . 我正在编写一个XNA引擎,我将所有模型存储在List In order to be able to use this throughout the engine, I've made this a public static List<Model> so I can access it from any new classes that I develop. 为了能够在整个引擎中使用它,我已经将它设置为public static List<Model>因此我可以从我开发的任何新类访问它。 It certainly makes obtaining the list of models really easy to get too, but is this the right usage? 它当然使获得模型列表真的很容易获得,但这是正确的用法吗? Or would I be better off actually passing a variable through in a method declaration? 或者我会更好地在方法声明中传递变量?

In OOP it's generally advisable to avoid using static methods and properties, unless you have a very good reason to do so. 在OOP中,通常建议避免使用静态方法和属性,除非您有充分的理由这样做。 One of the reasons for that is that in the future you may want to have two or more instances of this list for some reason, and then you'll be stuck with static calls. 其中一个原因是,由于某种原因,将来您可能希望拥有此列表的两个或更多实例,然后您将陷入静态调用。

Static methods and properties are too rigid. 静态方法和属性太僵硬了。 As Stevey states it: 正如Stevey所述:

Static methods are as flexible as granite. 静态方法与花岗岩一样灵活。 Every time you use one, you're casting part of your program in concrete. 每次使用一个,你都会在具体的时候投入你的程序的一部分。 Just make sure you don't have your foot jammed in there as you're watching it harden. 当你看着它变硬时,确保你的脚没有卡在那里。 Someday you will be amazed that, by gosh, you really DO need another implementation of that dang PrintSpooler class, and it should have been an interface, a factory, and a set of implementation classes. 有一天,你会感到惊讶的是,通过天哪,你真的需要另一个实现那个dang PrintSpooler类,它应该是一个接口,一个工厂和一组实现类。 D'oh! D'哦!

For game development I advocate "Doing The Simplest Thing That Could Possibly Work". 对于游戏开发,我提倡“做最可能工作的最简单的事情”。 That includes using global variables ( public static in C#), if that is an easy solution. 这包括使用全局变量(C#中的public static ),如果这是一个简单的解决方案。 You can always turn it into something more formal later. 你可以随时把它变成更正式的东西。 The "find all references" tool in Visual Studio makes this really easy. Visual Studio中的“查找所有引用”工具使这非常简单。

That being said , there are very few cases where a global variable is actually the "correct" way to do something. 话虽如此 ,极少数情况下全局变量实际上是做某事的“正确”方式。 So if you are going to use it, you should be aware of and understand the correct solution. 因此,如果您打算使用它,您应该了解理解正确的解决方案。 So you can make the best tradeoff between "being lazy" and "writing good code". 因此,您可以在“懒惰”和“编写好代码”之间做出最佳权衡。

If you are going to make something global, you need to fully understand why you are doing so. 如果你要创造一些全球化的东西,你需要完全理解你为什么要这样做。

In this particular case, it sounds like you're trying to trying to get at content. 在这种特殊情况下,听起来你正试图尝试获取内容。 You should be aware that ContentManager will automatically return the same content object if you ask for it multiple times. 您应该知道,如果多次请求, ContentManager将自动返回相同的内容对象。 So rather than loading models into a global list, consider making your Game class's built-in ContentManager available via a public static property on your Game class. 因此,而不是装载模式为全球性的列表中,考虑让你的Game类的内置ContentManager通过提供public static你的财产Game类。

Or, better still, there's a method that I prefer, that I think is a bit better: I explain it in the answer to another question . 或者,更好的是,有一种我更喜欢的方法,我觉得有点好: 我在另一个问题的答案中解释它 Basically you make the content references private static in the classes that use them and pass the ConentManager into public static LoadContent functions. 基本上,您在使用它们的类中将内容引用ConentManager private static ,并将ConentManager传递给public static LoadContent函数。 This compartmentalises your use of static to individual classes, rather than using a global that is accessed from all over your program (which would be difficult to extricate later). 这将您对静态的使用划分为单个类,而不是使用从您的整个程序中访问的全局(这将很难在以后解脱)。 It also correctly handles loading content at the correct time . 它还可以在正确的时间正确处理加载内容。

I'd avoid using static as much as possible, over time you'll just end up with spaghetti code . 我会尽量避免使用静态,随着时间的推移,你最终会得到意大利面条代码

If you pass it in the constructor you're eliminating an unnecessary dependency, low coupling is good . 如果你在构造函数中传递它,你就消除了不必要的依赖, 低耦合是好的 The fewer dependencies there are, the better. 依赖性越少越好。

I would suggest to implement a Singleon object which encapsulates the model list. 我建议实现一个封装模型列表的Singleon对象​​。
Have a look at the MSDN singleton implementation . 看看MSDN单例实现

This is a matter of balance and trade-offs. 这是一个平衡和权衡的问题。

Of course, OOP purists will say that avoid such global variables at all costs, since it breaks code compartmentization by introducing something that goes "out of the box" for any module, and thus making it hard to maintain, change, debug etc. 当然,OOP纯粹主义者会说不惜一切代价避免这样的全局变量,因为它通过引入任何模块“开箱即用”的东西来破坏代码区分,从而使得难以维护,更改,调试等。

However, my personal experience has been that it should be avoided only if you are part of a very large enterprise solutions team, maintaining a very large enterprise-class application. 但是,我个人的经验是,只有当您是一个非常大的企业解决方案团队的一员,维护一个非常大的企业级应用程序时,才应该避免它。

For others cases, encapsulating globally-accessible data into a "global" object (or a static object, same thing) simplifies OOP coding to a great extent. 对于其他情况,将全局可访问数据封装到“全局”对象(或静态对象,同样的东西)中可以在很大程度上简化OOP编码。

You may get the middle-ground by writing a global GetModels() function that returns the list of models. 您可以通过编写返回模型列表的全局GetModels()函数来获得中间立场。 Or use DI to automatically inject the list of models. 或使用DI自动注入模型列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM