0

I am trying to create a .NET API which wraps and interfaces with a third-party C API. As such the semantics of the API are as follows:

There is a property which represents a list of strings in a binary file. There is a distinction to be drawn between this property having a list with zero entries, in which case the property will be written to the file with an empty list; and the list being omitted altogether, in which case the property will be omitted from the file.

In my current design, I'm using something like this:

public class InfoWrapper
{
    // Use an IList<T> to avoid running afoul of FxCop
    // rule CA1002: Do not expose generic lists.
    public IList<string> ItemsContainer { get; set; }
}

This would do the trick, of course, allowing me to distinguish between the "not set" and "empty list" cases, but the real problem is that it triggers another FxCop warning, CA2227: Collection properties should be read only. I need to be able to allow the user to set the property to a null value, and potentially back to a list if they change their mind after setting it to null. I could make the property read-only, with a pair of methods (say, DeleteItemsContainer() and CreateNewItemsContainer()), but in reality, I have several of these properties I need to handle the same way. Adding two methods per property is going to clutter up the API considerably. What would be a better approach here?

N.B. I realize I could just suppress the FxCop warning and be done with it, and that those rules are just one set of suggestions. However, I'd like to stay within those guidelines if possible.

JimEvans
  • 27,201
  • 7
  • 83
  • 108

2 Answers2

1

I think you're confusing (or asking about) two issues: returning null versus an empty collection, and having a public setter which triggers the FxCop warning. You can return null regardless of whether the type is List or IList, so no issue there.

If you want to avoid that FxCop warning about the public setter, you'll need to make the setter private and provide another way to set the value of that property. You could pass an IList via the constructor of InfoWrapper, or if it makes sense just create the list in the constructor and add all the items to it after construction.

Patrick Quirk
  • 23,334
  • 2
  • 57
  • 88
  • No, I'm specifically asking about the public setter; the accessor being able to return `null` is not, and never has been a problem. The consumers of this API must have a way to set the collection represented by the property to null. A setter seemed the most straightforward way, but the FxCop rule recommends against it. I could create a method to set the property to null, but that's a one-way operation. I'll need a second method to reset it to empty if the user changes her mind. And since in reality I have four or five such properties in my object, that's going to make the API very inelegant. – JimEvans Oct 31 '12 at 00:06
  • Ok so you do need the setter, but don't want the warning that comes with it. I don't know what other option you have than to suppress the warning. That's certainly better than coming up with some alternte scheme for clearing the property and confusing the API just to avoid an FxCop warning. – Patrick Quirk Oct 31 '12 at 00:18
0

First the property has to be read-only, that is, not have a setter. But even then you would get another FxCop warning since the collection can still be modified by users.

A clean way to get rid of that FxCop warning is to change the definition of your property from returning an IList<T> to returning an IEnumerable<T>.

Like this:

public IEnumerable<string> StringList { get; set; }

If you can live without properties such as Count and the indexer, using IEnumerable helps ensure that the class users won't mess with the list contents.

(By the way, neither the term "String" nor "List" is recommended when naming a property. "String" doesn't indicate the semantics of the property, and "List" exposes the type of collection which should be encapsulated)

Ran
  • 5,989
  • 1
  • 24
  • 26
  • Using "StringList" in this case was merely for illustrative purposes. The actual property name is descriptive in its context, but thanks for pointing that out. – JimEvans Oct 30 '12 at 23:56
  • Additionally, the issue I'm hitting isn't that I'm hitting the "don't expose generic lists" warning, but rather that I'm hitting the "collection properties should be read-only" warning. – JimEvans Oct 31 '12 at 00:07
  • I wasn't referring to "don't expose generic lists" - that would be the case if you defined the property as a `List` instead of `IList`. My point was to use `IEnumerable` which is a read-only interface. Edited the answer to clarify. – Ran Oct 31 '12 at 00:19
  • That doesn't coincide with my experience. Simply removing the public getter resolves the warnings. I do not have an FxCop warning if my property is read-only, even if it returns `IList`. – JimEvans Oct 31 '12 at 00:29
  • Maybe you are using the minimal rule set and have this rule disabled? – Ran Oct 31 '12 at 05:21