与objects[i]相比,objects.GetObject(i) 有什么优势吗?
我正在重构前一位开发人员的一些 C# 数据访问代码,并对他使用的模式感到好奇。
该代码最初公开了各种 ActiveRecord 风格的业务对象的集合(数组)——本质上是包装数据库字段的对象。我正在将数组更改为通用列表,但我很好奇的代码方面是,以前的开发人员对于他所包装的每种类型的对象都有 Get 方法,因此:
public Thing GetThing(int i) {
return things[i];
}
这些方法有几种,我不能在我的一生中,我会考虑使用该机制相对于直接直接引用 things[i] 的任何可能的优势。为了便于论证,我们假设事物是公共财产,而不是公共字段(在这种情况下,它实际上是自动实现的财产,因此该假设实际上是正确的)。
我错过了一些明显的东西吗?甚至是一些深奥的东西?
更新 我可能应该澄清一下,这些集合当前是从 for 循环中访问的:
for (int i = 0; i < thingsCount; i== ) {
dosomthing( GetThing(i) );
dosomethingelse( GetThing(i) );
}
我正在重构:
for (int i = 0; i < thingsCount; i== ) {
Thing thing = things[i];
dosomthing( thing );
dosomethingelse( thing );
}
甚至可能使用 things.foreach()。
I'm refactoring a little bit of C# data access code from a previous developer and am curious about a pattern he used.
The code initially exposed collections (arrays) of a variety of ActiveRecord-style business objects - essentially objects wrapping database fields. I'm changing the arrays to generic lists, but the aspect of the code I'm curious about is that the previous developer had Get methods for each type of object he was wrapping, thusly:
public Thing GetThing(int i) {
return things[i];
}
There are several of these methods, and I cannot for the life of me think of any possible advantage of using that mechanism over simply referring to things[i] directly. Let's assume, for argument's sake, that things is a public property, not a public field (in this case it's actually an auto-implemented property, so that assumption is actually true).
Am I missing something obvious? Or even something esoteric?
UPDATE
I should probably clarify that these collections are currently accessed from within for loops:
for (int i = 0; i < thingsCount; i== ) {
dosomthing( GetThing(i) );
dosomethingelse( GetThing(i) );
}
which I am refactoring to:
for (int i = 0; i < thingsCount; i== ) {
Thing thing = things[i];
dosomthing( thing );
dosomethingelse( thing );
}
and perhaps even to use things.foreach().
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我不知道这是否很明显,但我确实认为你错过了一些东西。
假设
things
是一个IList
。然后直接公开它(作为Things
)将允许调用代码调用Add
、Insert
、RemoveAt
等。也许以前的开发人员不想允许这样做(我确信有很多充分的理由)。即使假设它是一个
Thing[]
(因此Add
等将不可用),将其公开仍然允许调用代码执行类似的操作obj.Things[0] = new Thing();
这可能是不应允许的操作,具体取决于类的实现。您可以将
Things
公开为ReadOnlyCollection
,这可以解决大部分问题。但归根结底是这样的:如果开发人员仅想要允许调用代码通过索引访问项目(仅此而已),那么提供一个GetThing
方法作为老实说,这样做的方法是迄今为止最有意义的。现在,当然,还有这个选项:仅使用
get
访问器实现this[int]
属性。但只有当相关类本质上是Thing
对象的专门集合时,这才有意义(即,不存在也一些其他的集合) em> 您想要在类中提供访问的对象类型)。总而言之,我认为
GetThing
方法非常合理。也就是说,从您提出问题的方式来看,听起来确实是之前的开发人员做出了一些其他相当糟糕的决定:
things
集合直接作为公共财产,那么...这违背了 GetThing 方法的全部目的,不是吗?结果只是一个臃肿的界面(我通常认为,当您有多种方法来完成完全相同的事情时,这不是一个好兆头,除非出于某种合理的原因将它们明确记录为别名)。 [更新:看来之前的开发者没有这样做。很好。]GetThing
方法从things
访问项目,这很愚蠢(在我看来)。为什么要从类本身内部使用类的公共接口引入额外方法调用的无意义开销?如果您在课堂上,那么您已经处于实现内部并且可以访问您想要的所有私有/受保护数据 - 无需假装。I don't know if it's obvious, but I do think you're missing something.
Let's say
things
is anIList<Thing>
. Then exposing it directly (asThings
) would allow calling code to callAdd
,Insert
,RemoveAt
, etc. Maybe the previous developer didn't want to allow this (and I'm sure there are plenty of good reasons for that).Even supposing it's a
Thing[]
(soAdd
, etc. wouldn't be available), exposing it as such would still allow calling code to do something likeobj.Things[0] = new Thing();
which may be an operation that should not be allowed depending on the class's implementation.You could expose
Things
as aReadOnlyCollection<Thing>
which would take care of most of these problems. But what it comes down to is this: if the developer only wants to allow calling code to access items by index -- nothing more -- then providing a singleGetThing
method as the means to do so, honestly, makes by far the most sense.Now, granted, there's also this option: implementing a
this[int]
property with only aget
accessor. But that only makes sense if the class in question is essentially a collection ofThing
objects exclusively (i.e., there isn't also a collection of some other type of object you want to provide access to within the class).All told, I think the
GetThing
approach is pretty sound.That said, from the way you've worded your question, it does sound like the previous developer made some other pretty poor decisions:
things
collection directly as a public property, well, then... that defeats the whole purpose of theGetThing
method, doesn't it? The result is simply a bloated interface (I generally think it's not a great sign when you've got multiple methods to accomplish exactly the same thing, unless they're clearly documented as aliases for some justifiable reason). [Update: It appears the previous developer did not do this. Good.]things
using theGetThing
method, which is just silly (in my opinion). Why introduce the pointless overhead of extra method calls using a class's public interface from within the class itself? If you're in the class, you're already inside the implementation and can access private/protected data all you want -- no need to pretend otherwise.您可能希望将该对象公开为
IList
。这将为您提供所需的索引功能,但您还可以使用一系列 LINQ 函数,例如根据条件创建新的项目列表。另外,IList
实现IEnumerable
,因此您将能够使用foreach
循环访问对象。例如在你的课堂上:
例如用法:
或
You probably want to expose the object as an
IList<Thing>
. This will give you the indexing capabilities you're looking for, but you also get to use the range of LINQ functions as well, such as creating a new list of items based on conditions. PlusIList<T>
implementsIEnumerable<T>
so you're going to be able to useforeach
to loop through the objects.e.g. in your class:
e.g. usage:
or
这里有两件事需要注意。首先,您希望将对象变量保持私有并使用 getter 和 setter 来访问它们。这可以防止用户意外更改或修改对象变量。
其次,它被认为是一个很好的命名约定,其中在直接访问属性时必须使用术语 get/set。这有助于提高可读性。
尽管在本例中它是公共财产,但使用 getter 和 setter 可以提高可读性并有助于防止意外行为。如果您在循环中访问对象变量并不重要,您应该继续使用
GetThing
约定。最后,如果您从对象内部访问变量,则不需要使用 getter 或 setter。
注意:它通常被认为是保持对象变量私有并为所有语言使用 getters/setters 的良好风格
C++ 风格指南
C# 风格指南
您可以也对问题“c# 类中的类的 getter 和 setter 感兴趣< /a>”
There are two things to note here. First is that you want to keep object variables private and use getters and setters to access them. This prevents the user from accidentally changing or modifying object variables.
Secondly, it is considered a good naming convention where the terms get/set must be used where an attribute is accessed directly. This helps improve readability.
Although it is a public property in this case, the use of getters and setters improve readability and help prevents unexpected behavior. It doesn't matter if you are accessing the object variables within a loop, you should continue to use the
GetThing
convention.Finally if you are accessing the variables from within the object, you don't need to use the getter or setter.
NOTE: Its generally considered good style to keep object variables private and use getters/setters for all languages
C++ style guidelines
C# style guidelines
You may also be interested in the question "getter and setter for class in class c#"
如果我不得不猜测,我会说该开发人员习惯了 Java 等其他语言,并且不完全了解 C# 中的标准实践。 “get[Property]”术语在 Java、javascript 等中使用非常频繁。C# 用属性和索引器替换了它。属性与 getter 和 setter 一样强大,但更易于编写和使用。在 C# 中,您通常看到“Get[something]”的唯一情况是:
GetPrimeNumbers()< /code>),或者
GetRow(int i)
和GetColumn(int i))
。即使在这种情况下,更常见的做法是简单地将每个索引集合作为其自身的属性公开,该属性属于索引类型(“table.Rows[2]
”)。如果您仅在
for
循环中访问这些值,则该集合应该实现IEnumerable
,这将使您能够访问LINQ方法和foreach
构造。如果您仍然需要基于索引的 getter,您应该考虑使用您自己的接口,该接口扩展了IEnumerable
,但还提供了:这样,您就不会给消费者留下这样的印象:他们可以
添加
和删除
此集合中的对象。更新
我知道这主要是一个风格问题,这是有争议的,但我真的认为
GetThings
解决方案不是正确的做事方式。以下策略虽然需要更多工作,但更符合标准 .NET 类和框架的设计方式:使用上面的代码可能看起来像这样:
If I had to guess, I'd say that this developer was used to some other language like Java, and wasn't fully aware of standard practice in C#. The "get[Property]" nomenclature is very heavily used in Java, javascript, etc. C# replaces this with properties and indexers. Properties are every bit as powerful as getters and setters, but are easier to write and use. The only time you typically see "Get[something]" in C# is if:
GetPrimeNumbers()
), orGetRow(int i)
andGetColumn(int i))
. Even in this case, it's more common to simply expose each of these indexed collections as a property unto itself, which is of an indexed type ("table.Rows[2]
").If you are only accessing these values in
for
loops, the collection should implementIEnumerable<Thing>
, which would give you access to LINQ methods and theforeach
construct. If you still need to have indexed-based getters, you should consider using your own interface which extendsIEnumerable<T>
, but additionally provides:This way, you don't give consumers the impression that they can
Add
andRemove
objects in this collection.Update
I know this is mostly a matter of style, which is subject to debate, but I really think the
GetThings
solution is not the correct way to do things. The following strategy, while it takes a little more work, is far more in keeping with the way that the standard .NET classes and frameworks are designed:Using the code above might look something like this:
就像其他答案所指出的那样,这是限制对数组(或列表)本身的访问的问题。
一般来说,您不希望类的客户端能够直接修改数组本身。隐藏基础列表的实现还允许您将来更改实现,而不会影响使用该类的任何客户端代码。
Like the other answers have indicated, it's an issue of restricting access to the array (or list) itself.
In general, you don't want clients of the class to be able to directly modify the array itself. Hiding the implementation of the underlying list also allows you to change the implementation in the future without affecting any client code that uses the class.