Does List.Contains(mystring) do a reference comparison or a value comparison? Eg I have this code:
/// <summary>
/// If the value isn't null or an empty string,
/// and doesn't exist in the list, it adds it to the list
/// </summary>
static void AddToListIfNotEmpty(List<string> thelist, SqlString val)
{
string value = val.ToString().Trim();
if (!string.IsNullOrEmpty(value))
{
bool found = false;
foreach (string x in thelist) if (x == value) found = true;
if (!found) thelist.Add(value);
}
}
Can i simplify the foreach and following line to:
if (!thelist.Contains(value)) thelist.Add(value);
Thanks
IList<T>
uses Comparator<T>.Default
to do the comparisons, and in turn that compares by value for String
objects.
If you wanted to, you could move your items to an IDictionary<T, bool>
or something similar, where you can specify your IComparator
- specifying one that checks for reference. (even though in that case, you're better off with the foreach loop)
If you can use LINQ, you could create a statement there with a reference comparison, too.
Comparing for all strings is overloaded to be by value. Sorry didn't notice you had a SqlString, why not use it's ToString() method and add that? Your shortened method won't compile.
From MSDN of List<T>.Contains
This method determines equality using the default equality comparer
EqualityComparer<T>.Default
for T, the type of values in the list.... The Default property checks whether type T implements the
IEquatable<T>
generic interface and if so returns anEqualityComparer<T>
that uses that implementation. Otherwise it returns anEqualityComparer<T>
that uses the overrides ofObject.Equals
andObject.GetHashCode
provided byT
.
Looking at reflector (and by the principle of least surprise), String Equality has value type semantics - so they are equal if they have the same strings. Both Equals(Object)
and IEquatable.Equals(T)
delegate to String::EqualsHelper
Yes, you can simplify (in terms of code, not complexity *) by removing the foreach, but your simplification is not functionally identical to your original.
The simplied, functional equivalent would be:
static void AddToListIfNotEmpty(List<string> thelist, SqlString val)
{
string value = val.ToString().Trim();
if (value != string.Empty && !thelist.Contains(value))
thelist.Add(value);
}
Note that your string.IsNullOrEmpty()
will never encounter a null
reference for the string. Edit : after checking, I noticed that the SqlString.ToString()
method converts a NULL SqlString to a literal value "Null", which is not what you want, I imagine. You should add this as the first thing to do in your method:
if (val.IsNull)
return;
Lastly, returning to my complexity comment: if you're dealing with a large amount of elements, you might want to look at HashSet
instead of using a List
(same namespace). It won't maintain the order in which strings are added, but it's Contains
operation is O(1) , while your current one is O(n) .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.