not sure which type to use for a property IEnumerable or List
I have the following class which is quite wide usely throughout my application :
public class ResultStatus
{
public Int32 Id {get; protected set}
public ErrorCode ErrorCode {get; protected set;}
List<string> UserMessages {get; protected set;}
protected ResultStatus (Int32 id, ErrorCode errorCode, List<string> userMessages)
{
Id = id;
ErrorCode = errorCode;
UserMessages = userMessages;
}
public static ResultStatus Success (int32 id, ErrorCode errorCode, IEnumerable<string> userMessages)
{
ResultStatus resultStatus = new ResultStatus (id, errorCode, userMessages.ToList());
return resultStatus;
}
}
I am concerned with the casting from the IEnumerable type of the parameter to List() and Im thinking of changing the property UserMessages type from List to IEnumerable to avoid the cast. However in the projects that use this class, sometimes a Count is applied or the list is a开发者_开发百科ccessed directly by index. So what I gain by avoiding a cast, I loose by using the Count of the IEnumerable for instance which iterates throughout the collection. What is the nice way of doing this? Leave it like this, List type property - parameter casting from IEnumerable to List or change the type of the property and not be concerned on the few Counts ?
To internally store the information you need to use a List<T>
or a similar structure. You can't just save the IEnumerable<T>
you got passed in. The enumerable might not be valid once the function returns, or it might only allow iterating once,...
As for the type of public properties I like using ReadOnlyCollection<T>
.
I would change everything to IEnumerable<string>
or if you need to access the error messages by index use IList<string>
.
It's OK to use a calss such as List<> internally for your class's field.
But it's advised to avoid exposing such a type explicitly in your class public API. Rather, use the most general interface that meets your needs. So the property should be an IEnumerable<> or an IList, if you need to allow access to Count or indexed access.
Also, you should consider whether or not you wish to allow the class's user to modify the property.
Right now, you are providing a reference to the List itself. Meaning that someone can do:
ResultStatus myResult = GetSomeResult();
myResult.UserMessages.Clear();
If you wish to avoid such behavior, you may want to change your property to return a copy of the internal List field.
To build on @CodeInChaos answer, I would change the UserMessages
property to ReadOnlyCollection<string>
and change the signature of the Success
method to
public static ResultStatus Success(int32 id, ErrorCode errorCode, List userMessages)
This way, the conversion to List<string>
is offloaded to the calling method - which is probably using a List already and the UserMessages property can't be used to modify the underlying collection.
public class ResultStatus
{
public Int32 Id {get; protected set}
public ErrorCode ErrorCode {get; protected set;}
ReadonlyCollection<string> UserMessages {get; protected set;}
protected ResultStatus (Int32 id, ErrorCode errorCode, List<string> userMessages)
{
Id = id;
ErrorCode = errorCode;
UserMessages = userMessages.AsReadOnly();
}
public static ResultStatus Success (int32 id, ErrorCode errorCode, List<string> userMessages)
{
ResultStatus resultStatus = new ResultStatus (id, errorCode, userMessages);
return resultStatus;
}
}
精彩评论