CA1819:属性不应返回数组 - 正确的替代方案是什么?

发布于 2024-12-11 01:57:23 字数 1050 浏览 0 评论 0原文

我之前遇到过这个 FxCop 规则,并且并不真正满足于如何解决违规问题(线程1线程2)。我现在有另一个案例,我需要纠正违反 CA1819 类型。

具体来说,我有一个算法库,它对曲线 (x,y) 执行一些分析计算,具有如下所示的公共“输入对象”:

public class InputObject
{
        public double[] X { get; set; }
        public double[] Y { get; set; }
        // + lots of other things well
}

该对象的 X 和 Y 属性在库内的数百个位置使用,通常使用索引。输入对象永远不会被算法改变,但实际上如果是这样也没关系。此外,.Length 的调用也非常频繁。它是一个数学库,double[] 是其中的标准数据类型。无论如何,修复 CA1819 需要做相当多的工作。

我考虑过使用 List,因为列表支持索引并且与数组非常相似,但我不确定这是否会减慢算法速度,或者 FxCop 是否会对这些列表感到满意。

替换这些 double[] 属性的最佳选择是什么?

I encountered this FxCop rule before and wasn't really content with how to solve violations (thread1, thread2). I now have another case where I need to correct violations of the CA1819 kind.

Specifically, I have an algorithm-library that performs some analytic calculations on a curve (x,y), with a public "input object" like this:

public class InputObject
{
        public double[] X { get; set; }
        public double[] Y { get; set; }
        // + lots of other things well
}

This object's X and Y properties are used in hundreds of locations within library, typically using indexes. The input object is never altered by the algorithms, but actually it shouldn't matter if so. Also, .Length is called pretty frequently. It's a mathematical library, and double[] is kind of the standard data type in there. In any case, fixing CA1819 will require quite some work.

I thought about using List<double>, since Lists support indexing and are quite similar to arrays but I'm not sure whether this may slow down the algorithms or whether FxCop will be happy with those Lists.

What is the best option to replace these double[] properties?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

℉服软 2024-12-18 01:57:23

如果它对外部使用者是只读的,并且使用者不想通过索引访问它,那么最好是拥有一个 IEnumerable<> 类型的公共只读属性,并带有用于添加和删除的方法访问器,这样你就不必将你的数组暴露给别人来打扰。

如果您需要访问索引器,请将其公开为 IList 类型的只读属性,并可能返回一个 ReadOnly 实例,其中包含添加和删除的方法。

通过这种方式,您可以保留内部列表的封装并允许消费者以只读方式访问它

If it is read only to external consumer and consumer does not want to access it by index then the best is to have a public read only property of type IEnumerable<> with method accessors to add and remove, this way you will not have to expose your array to someone to mess with.

If you need to access the indexers then expose it as read only property of type IList<> and probably return a ReadOnly instance, with methods to add and remove.

This way you keep encapsulation of the internal list and allow consumer to access it in a read only way

月亮坠入山谷 2024-12-18 01:57:23

从我的角度来看,FxCop 有时有些夸大其词。

这一切都取决于您必须做什么,如果您正在编写一个需要安全性和非常干净的代码的复杂系统,您应该返回该数组的只读版本。
也就是说,按照 devdigital 的建议将数组转换为 IEnumerable,或者使用我更喜欢的 Mohamed Abed 的 ImmutableArray 好主意。

如果您正在编写需要高性能的软件...在 C# 中没有什么比数组更好的性能了。
数组的迭代和读取性能要高得多。

如果表演真的很重要,我建议您忽略该警告。
返回只读数组仍然是合法的,即使不是太干净。

for (int i = 0; i < array.Length; ++i) { k = array[i] + 1; }

这对于 C# 中的大数组来说非常快:它避免了数组边界检查。
它的执行效果与 C 编译代码非常相似。

我一直希望 C# 中有一个“只读数组”类型:)但没有希望看到它。

Sometime FxCop from my point of view exagerates.

It all depends on what you have to do, if you are writing a complex system where security and very clean code is required, you should returns a readonly version of that array.
That is, cast the array as IEnumerable as suggests devdigital or use the good idea ImmutableArray of Mohamed Abed, that i prefer.

If your are writing software that require high performance... there is nothing better than an array for performances in C#.
Arrays can be a lot more performant for iterating and reading.

If performances are really important I suggest you to ignore that warning.
Is still legal, also if not too much clean, to return a readonly array.

for (int i = 0; i < array.Length; ++i) { k = array[i] + 1; }

This is very fast for big arrays in C#: it avoids array bounds check.
It will perform very much as a C compiled code would do.

I always wished a "readonly array" type in C# :) but there is no hope to see it.

蒲公英的约定 2024-12-18 01:57:23

正如您的链接所示:

要解决违反此规则的问题,请将该属性设置为方法,或者
更改属性以返回集合。

使用诸如List之类的集合不会对性能产生重大影响。

As your link suggests:

To fix a violation of this rule, either make the property a method or
change the property to return a collection.

Using a collection such as a List should not have a significant impact on performance.

无人问我粥可暖 2024-12-18 01:57:23

这里的大问题并不是你的库如何处理这些值(这是一个潜在的问题,尽管更容易管理),而是调用者可能如何处理这些值。如果您需要将它们视为不可变,那么您需要确保库使用者在原始分配后无法更改内容。这里的简单修复方法是创建一个公开您的库使用的所有数组成员的接口,然后为实现此接口的数组创建一个不可变的包装类,以便在您的 InputObject 类中使用。例如:

public interface IArray<T>
{
    int Length { get; }

    T this[int index] { get; }
}

internal sealed class ImmutableArray<T> : IArray<T>
    where T : struct
{
    private readonly T[] _wrappedArray;

    internal ImmutableArray(IEnumerable<T> data)
    {
        this._wrappedArray = data.ToArray();
    }

    public int Length
    {
        get { return this._wrappedArray.Length; }
    }

    public T this[int index]
    {
        get { return this._wrappedArray[index]; }
    }
}

public class InputObject
{
    private readonly IArray<double> _x;
    private readonly IArray<double> _y;

    public InputObject(double[] x, double[] y)
    {
        this._x = new ImmutableArray<double>(x);
        this._y = new ImmutableArray<double>(y);
    }

    public IArray<double> X
    {
        get { return this._x; }
    }

    public IArray<double> Y
    {
        get { return this._y; }
    }

    //...
}

如果 T 是可变的,“不可变”数组内容中的元素仍然是可变的,但至少对于 double 类型是安全的。

The big problem here isn't really what your library does with the values (which is a potential problem, albeit a much more manageable one), but rather what callers might do with the values. If you need to treat them as immutable, then you need to ensure that a library consumer cannot change the contents after their original assignment. The easy fix here would be to create an interface that exposes all the array members that your library uses, then create an immutable wrapper class for an array that implements this interface to use in your InputObject class. e.g.:

public interface IArray<T>
{
    int Length { get; }

    T this[int index] { get; }
}

internal sealed class ImmutableArray<T> : IArray<T>
    where T : struct
{
    private readonly T[] _wrappedArray;

    internal ImmutableArray(IEnumerable<T> data)
    {
        this._wrappedArray = data.ToArray();
    }

    public int Length
    {
        get { return this._wrappedArray.Length; }
    }

    public T this[int index]
    {
        get { return this._wrappedArray[index]; }
    }
}

public class InputObject
{
    private readonly IArray<double> _x;
    private readonly IArray<double> _y;

    public InputObject(double[] x, double[] y)
    {
        this._x = new ImmutableArray<double>(x);
        this._y = new ImmutableArray<double>(y);
    }

    public IArray<double> X
    {
        get { return this._x; }
    }

    public IArray<double> Y
    {
        get { return this._y; }
    }

    //...
}

The elements in your "immutable" array contents would still be mutable if T is mutable, but at least you're safe for the double type.

朮生 2024-12-18 01:57:23

将 array[] 更改为 IEnumerable:

public class InputObject
{
    public IEnumerable<double> X { get; set; }
    public IEnumerable<double> Y { get; set; }
    // + lots of other things well
}

Change array [] to IEnumerable:

public class InputObject
{
    public IEnumerable<double> X { get; set; }
    public IEnumerable<double> Y { get; set; }
    // + lots of other things well
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文