【问题标题】:Static IEnumerator静态 IEnumerator
【发布时间】:2012-11-02 22:03:39
【问题描述】:

如何通过实现 Array Wrapper 来最小化开销?

1 为 MyProviderInfos 选择哪种接口/类型?

2 使用 private static 枚举器是否合理? 不,从 answer

3 应该 MyProviderInfos 是一个属性以及如何保护其成员免受修改? 成员的内部/私有设置器(来自相同的答案)

我尝试浏览有关 ICollection、Readonly-Collection、List、IList、Array 的 SO 文章,但仍然对最适合该场景的内容感到困惑:

  • 数组 MyProviderInfos 由编译时形成,不会(不得)在运行时更改。
  • 该类(必须)是可枚举的(使用数组 MyProviderInfos 的元素)并且不需要自定义列表函数(.Add .Remove)。
  • 类有静态函数,使用数组。
  • 类必须是非静态的才能支持索引。

代码:

 public class MyIdentifiers : IEnumerable<MyProviderInfo>
 {
   //public static IList<MyProviderInfo> getMyProviderInfos() 
   //{ return MyProviderInfos; }

    public static int MyProviderCount()
    {
        return MyProviderInfos.Count;
    }

    public static readonly IList<MyProviderInfo> MyProviderInfos = new[]
    {
        new MyProviderInfo
            {
                MyProvider = MyProvider.FirstProvider,
                Url = "https://www.google.com",                       
            }
    };

    private static IEnumerator<MyProviderInfo> _enumerator = 
((IEnumerable<MyProviderInfo>)MyProviderInfos).GetEnumerator();

    public IEnumerator<MyProviderInfo> GetEnumerator()
    {
        return _enumerator;
        //return ((IEnumerable<MyProviderInfo>)MyProviderInfos).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

}

【问题讨论】:

    标签: c# arrays list static enumerator


    【解决方案1】:

    为 MyProviderInfos 选择哪种接口/类型?

    除非您想限制用户直接可见的功能,否则您应该始终返回 less generic 类型(在您的情况下是数组本身)。

    作为一般规则,接受最通用的可能类型作为参数是一个好习惯(例如,如果您只想枚举一个集合,然后将该参数声明为IEnumerable&lt;T&gt;)并作为结果不太通用(因此用户可以使用如果他们只是需要它作为IEnumerable&lt;T&gt;,或者作为IList&lt;T&gt;,根据需要,没有脆弱的转换和转换)。此外,在您的情况下,IList&lt;T&gt; 支持添加项目,但这会在运行时抛出,因为数组是固定大小的,因此您公开的内容超出了他们实际可以做的范围。

    例如:

    string[] ConvertToTitleCase(IEnumerable<string> names);
    

    当然,您也可以返回 IEnumerable&lt;string&gt; 而不是 string[],这可能是合适的 - 例如 - 实现没有为结果创建任何数组以避免额外的转换。

    使用私有静态枚举器合理吗?

    绝对不是,枚举器是一个有状态的对象(看看任何IEnumerator&lt;T&gt; 实现)然后它不能是静态的(想象一下当被不同的线程调用时,例如)。

    MyProviderInfos 是否应该是一个属性以及如何保护其成员不被修改?

    它不需要是一个属性,除非你想提供某种惰性初始化。为了保护它的成员,你唯一能做的就是让它们只读(如果集合本身是只读的并不重要)。如何做到这一点取决于MyProviderInfo 的实现。您可以考虑不要为其属性公开任何public setter。例如:

    class MyProviderInfo
    {
        public MyProviderInfo(Provider provider, string url)
        {
            Provider = provider;
            Url = url;
        }
    
        public Provider Provider
        {
            get;
            private set;
        }
    
        public string Url
        {
            get;
            private set;
        }
    }
    

    或者,无需太多更改,保留现有代码,但将 setter 设置为内部(因此您的库的用户将无法修改它们):

    class MyProviderInfo
    {
        public Provider Provider
        {
            get;
            internalset;
        }
    
        public string Url
        {
            get;
            internal set;
        }
    }
    

    总结一下,我会重写如下:

     public class MyIdentifiers : IEnumerable<MyProviderInfo>
     {
        public int Count
        {
            get { return _myProviderInfos.Count; }
        }
    
        public IEnumerator<MyProviderInfo> GetEnumerator()
        {
            return ((IEnumerable<MyProviderInfo>)_myProviderInfos ).GetEnumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    
        private static readonly IList<MyProviderInfo> _myProviderInfos = new[]
        {
            new MyProviderInfo
                {
                    MyProvider = MyProvider.FirstProvider,
                    Url = "https://www.google.com",                       
                }
        };
     }
    

    【讨论】:

    • 感谢您的快速回答,Adriano,内部二传手 - 很明显,只是在确认。我想知道从 MyIdentifiers 实例获取 Enumerator 的工作方式是否与直接从 _myProviderInfos 使用属性 get { return _myProviderInfos; }
    • 少数函数调用的开销很难衡量(而且可能是这样的纳米优化,你甚至不应该关心它)无论如何 JIT 编译器会内联它,所以完全不用担心(也不要忘记与直接数组访问相比,枚举本身非常慢)。
    猜你喜欢
    • 1970-01-01
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-08
    • 2017-10-15
    • 2012-04-01
    • 1970-01-01
    相关资源
    最近更新 更多