代码之家  ›  专栏  ›  技术社区  ›  cori

对objects.GetObject(i)有什么好处吗?

  •  6
  • cori  · 技术社区  · 14 年前

    该代码最初公开了各种ActiveRecord样式的业务对象的集合(数组)——本质上是包装数据库字段的对象。我正在将数组更改为泛型列表,但我对代码的一个方面很好奇,即以前的开发人员为他包装的每种类型的对象都有Get方法,因此:

    public Thing GetThing(int i) {
        return things[i];
    }
    

    这些方法有好几种,我一辈子都想不出使用这种机制比直接引用事物有什么好处。为了论证,让我们假设things是一个公共属性,而不是一个公共字段(在本例中,它实际上是一个自动实现的属性,所以这个假设实际上是正确的)。

    我是不是漏掉了什么明显的东西?或者是什么深奥的东西?

    更新 我应该澄清一下,这些集合当前是从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 );
    }
    

    甚至可以使用东西。foreach()。

    5 回复  |  直到 14 年前
        1
  •  6
  •   Dan Tao    14 年前

    我不知道这是否明显,但我确实认为你遗漏了什么。

    比如说 things IList<Thing> Things )允许调用代码调用 Add Insert , RemoveAt 可能之前的开发人员不想允许这样做(我相信有很多很好的理由)。

    Thing[] (所以 ,等),这样暴露它仍然允许调用代码执行以下操作 obj.Things[0] = new Thing(); 根据类的实现,可能是不允许的操作。

    能够 暴露 东西 作为一个 ReadOnlyCollection<Thing> 解决了大部分问题。但归根结底是这样的:如果开发商 只有 GetThing 老实说,方法作为实现这一目标的手段是最有意义的。

    当然,现在还有一个选择:实现 this[int] get 存取器。但只有当所讨论的类本质上是 Thing 对象独占(即没有 其他 要在类中提供访问权限的对象的类型)。

    总而言之,我认为 获得 方法很合理。

    1. 如果他/她 暴露了 获得 更新 :似乎是上一个开发人员做的 做这个。好的。]
    2. 内部 从访问项目 使用 获得 方法,这是愚蠢的(在我看来)。为什么要从类本身引入使用类的公共接口的额外方法调用的无意义开销?如果你在班上,你已经 并且可以访问所有您想要的私有/受保护的数据--无需假装其他方式。
        2
  •  2
  •   Warren Rumak    14 年前

    IList<Thing> . 这将为您提供所需的索引功能,但您也可以使用LINQ函数的范围,例如根据条件创建新的项目列表。加 IList<T> 工具 IEnumerable<T> 所以你可以使用 foreach 在物体之间循环。

    public IList<Thing> Things { get; private set; }
    

    e、 g.用法:

    Thing x = business.Things[3];
    

    var x = business.Things.Where(t => t.Name == "cori");
    
        3
  •  2
  •   Community CDub    7 年前

    这里有两点需要注意。首先,您希望保持对象变量私有,并使用getter和setter来访问它们。这可以防止用户意外更改或修改对象变量。

    其次,它被认为是一种很好的命名约定,在直接访问属性时必须使用get/set。这有助于提高可读性。

    GetThing

    最后,如果要从对象内部访问变量,则不需要使用getter或setter。

    注意:它通常被认为是保持对象变量私有并对所有语言使用getter/setter的好风格

    C++ style guidelines

    C# style guidelines

    你也可能对这个问题感兴趣” getter and setter for class in class c# "

        4
  •  1
  •   StriplingWarrior    14 年前

    • 该操作可能会非常昂贵,以至于您真的想让自己明白这不是简单的成员访问(例如。 GetPrimeNumbers()
    • GetRow(int i) GetColumn(int i)) table.Rows[2] ").

    如果你是 只有 在中访问这些值 for 循环,集合应该实现 IEnumerable<Thing> foreach 构造。如果仍然需要基于索引的getter,那么应该考虑使用自己的接口来扩展 IEnumerable<T>

    T this[int i] { get; }
    

    这样,你就不会给消费者一种他们能做到的印象 Add Remove 此集合中的对象。

    我知道这主要是一个风格的问题,这是有争议的,但我真的认为 GetThings 解决问题不是正确的做事方法。下面的策略虽然需要更多的工作,但更符合标准.NET类和框架的设计方式:

    public class ThingHolderDataAccess
    {
        public ThingHolder GetThingHolderForSomeArgs(int arg1, int arg2)
        {
            var oneThings = GetOneThings(arg1);
            var otherThings = GetOtherThings(arg2);
            return new ThingHolder(oneThings, otherThings);
        }
        private IEnumerable<OneThing> GetOneThings(int arg)
        {
            //...
            return new List<OneThing>();
        }
        private IEnumerable<AnotherThing> GetOtherThings(int arg2)
        {
            //...
            return new List<AnotherThing>();
        }
    }
    
    public class ThingHolder
    {
        public IIndexedReadonlyCollection<OneThing> OneThings
        {
            get;
            private set;
        }
    
        public IIndexedReadonlyCollection<AnotherThing> OtherThings
        {
            get;
            private set;
        }
    
        public ThingHolder(IEnumerable<OneThing> oneThings,
                           IEnumerable<AnotherThing> otherThings)
        {
            OneThings = oneThings.ToIndexedReadOnlyCollection();
            OtherThings = otherThings.ToIndexedReadOnlyCollection();
        }
    }
    
    #region These classes can be written once, and used everywhere
    public class IndexedCollection<T> 
        : List<T>, IIndexedReadonlyCollection<T>
    {
        public IndexedCollection(IEnumerable<T> items)
            : base(items)
        {
        }
    }
    
    public static class EnumerableExtensions
    {
        public static IIndexedReadonlyCollection<T> ToIndexedReadOnlyCollection<T>(
            this IEnumerable<T> items)
        {
            return new IndexedCollection<T>(items);
        }
    }
    
    public interface IIndexedReadonlyCollection<out T> : IEnumerable<T>
    {
        T this[int i] { get; }
    }
    #endregion
    

    使用上面的代码可能如下所示:

    var things = _thingHolderDataAccess.GetThingHolderForSomeArgs(a, b);
    foreach (var oneThing in things.OneThings)
    {
        // do something
    }
    foreach (var anotherThing in things.OtherThings)
    {
        // do something else
    }
    
    var specialThing = things.OneThings[c];
    // do something to special thing
    
        5
  •  0
  •   David R Tribble    14 年前

    正如其他答案所指出的,这是一个限制对数组(或列表)本身的访问的问题。