Difference between the classes inherited from ObservableCollection and IList - c#

I have created the two different classes. One class inherited from IList and another one class inherited from ObservableCollection. When we create the instance for those classes, I got the below results.
Inherited from IList
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Cells = new CellCollection();
}
private CellCollection cells;
public CellCollection Cells
{
get { return cells; }
set { cells = value; }
}
}
public class CellCollection : IList<OrderInfo>
{
public CellCollection()
{
}
public OrderInfo this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public bool IsReadOnly => throw new NotImplementedException();
public int Count => throw new NotImplementedException();
public void Clear()
{
throw new NotImplementedException();
}
public bool Contains(OrderInfo item)
{
throw new NotImplementedException();
}
public void CopyTo(OrderInfo[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public IEnumerator<OrderInfo> GetEnumerator()
{
throw new NotImplementedException();
}
public int IndexOf(OrderInfo item)
{
throw new NotImplementedException();
}
public void Insert(int index, OrderInfo item)
{
throw new NotImplementedException();
}
public bool Remove(OrderInfo item)
{
throw new NotImplementedException();
}
public void RemoveAt(int index)
{
throw new NotImplementedException();
}
internal void Add(OrderInfo orderInfo)
{
}
void ICollection<OrderInfo>.Add(OrderInfo item)
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
Instance maintained for IList.
Inherited from ObservableCollection
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Cells = new CellCollection();
}
private CellCollection cells;
public CellCollection Cells
{
get { return cells; }
set { cells = value; }
}
}
public class CellCollection : ObservableCollection<OrderInfo>
{
public CellCollection()
{
}
}
Instance not maintained for Observable collection, Count only maintained
Could you explain the difference for both?

The debugger makes use of the debugger attributes the type is annotated with.
If a type does not use these attributes, the ToString() method of that type is called to get a text representation.
The ObservableCollection uses one of these methods to display the Count. Your own List implementation does none of this, so the base ToString() method is called which only returns the type name.
So to get a similar result for your own type, implement ToString() or annotate your CellCollection class with a DebuggerDisplayAttribute.

When the cursor is over a variable, you can see the variable name and the instance's debug label.
By default, the debug label is the result of ToString. For your class CellList, the method ToString cam from the base class Object and return the class's name. This display : CellList.
The attribute DebuggerDisplay allows define the instance's debug label (not to string). The class CellCollection inherit from ObservableCollection<T> than inherit from Collection<T> and the class Collection is declared with the attribute DebuggerDisplay.
[DebuggerDisplay("Count = {Count}")]
public class Collection<T>: IList<T>, IList, IReadOnlyList<T>
It's the same with all collection in .NET, like List.
If you set this attribute on your class CellList, you will see the same debug label.

Related

generic class with constraint IEqualityComparer

I am pretty new to Generic class in C#. I was trying to create one and ran into compiler error that I am not sure how to get around it.
Basically, I have a class G that implements ICollection
public class G<T> : ICollection<T> where T : IEqualityComparer
{
private ArrayList _members = new ArrayList();
public void Add(T item)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public bool Contains(T item)
{
throw new NotImplementedException();
}
public void CopyTo(T[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public int Count
{
get { throw new NotImplementedException(); }
}
public bool IsReadOnly
{
get { throw new NotImplementedException(); }
}
public bool Remove(T item)
{
throw new NotImplementedException();
}
public IEnumerator<T> GetEnumerator()
{
foreach (var item in _members)
{
yield return (T)item;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
I wanted to be able to do comparison in G and Find item in G, so I have put a constraint that T has to be implementing IEqualityComparer. Then, I have an actual class called IntegerClass that implement IEqualityComparer as below. So far, so good, no compiler error.
public class IntegerClass : IEqualityComparer<int>
{
public bool Equals(int x, int y)
{
throw new NotImplementedException();
}
public int GetHashCode(int obj)
{
throw new NotImplementedException();
}
}
However, when I tried to create an instance of G above. I got a compiler error.
class Program
{
static void Main(string[] args)
{
G<IntegerClass> i = new G<IntegerClass>();
}
}
The error is:
The type 'TestGeneric.IntegerClass' cannot be used as type parameter 'T' in the generic type or method 'TestGeneric.G<T>'.
There is no implicit reference conversion from 'TestGeneric.IntegerClass' to 'System.Collections.IEqualityComparer'
Could someone pinpoint what I have overlooked? Why would I need conversion? All I did was replacing class T with IntegerClass that implements IEqualityComparer interface. What should I do otherwise? I am new to this generic stuff, but have found it quite useful. I am thinking it could be very useful if I understand it correctly. Please help.
Update:
Based on some suggestion, I saw what was wrong and I updated the code as follow:
public class IntegerClass : IEqualityComparer
{
public bool Equals(object x, object y)
{
throw new NotImplementedException();
}
public int GetHashCode(object obj)
{
throw new NotImplementedException();
}
}
public class G<T> : ICollection<T> where T : IEqualityComparer
{
private ArrayList _members = new ArrayList();
public void Add(T item)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public bool Contains(T item)
{
throw new NotImplementedException();
}
public void CopyTo(T[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public int Count
{
get { throw new NotImplementedException(); }
}
public bool IsReadOnly
{
get { throw new NotImplementedException(); }
}
public bool Remove(T item)
{
throw new NotImplementedException();
}
public IEnumerator<T> GetEnumerator()
{
foreach (var item in _members)
{
yield return (T)item;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
I think it might work but I got the warning below:
'TestGeneric.IntegerClass.Equals(object, object)' hides inherited member 'object.Equals(object, object)'. Use the new keyword if hiding was intended.
I know object has an Equals methods but the warning does not make sense. Should it say use the new keyword if hiding was NOT intended?
Your constraint refers to the non-generic System.Collections.IEqualityComparer interface, which is not the same as IEqualityComparer<T>.
You could fix that error by specify the generic type in the constraint.
However, that's not what you want; an IEqualityComparer is a class that compares other things.
You want where T : IEquatable<T>.
change your IntegerClass like below.
public class IntegerClass : IEqualityComparer<IntegerClass>
{
public bool Equals(IntegerClass IC1, IntegerClass IC2)
{
throw new NotImplementedException();
}
public int GetHashCode(IntegerClass obj)
{
throw new NotImplementedException();
}
}
Or you could resort it to the fact that Objects has an equality function.
Hence, this would work
public interface IMyComparer
{
object Comparer { get; }
}
public class IntegerClass : IMyComparer, IEqualityComparer<int>
{
public object Comparer { get { return this; } }
public bool Equals(int x, int y)
{
throw new NotImplementedException();
}
public int GetHashCode(int obj)
{
throw new NotImplementedException();
}
}
public class G<T> : ICollection<T> where T : IMyComparer
{
Your implementations
}
Hope it helps.

What is the best way to add the Last property to a System.Array?

I tried the solution below but I don't like it. I am looking for extending the class, not encapsulating a double[].
Thanks.
EDIT: We need to work with .NET 2.0
public class DoubleArray : IList, ICloneable
{
protected double[] items;
/// <summary>
/// Gets the last item in the array.
/// </summary>
public double Last { get { return items[items.Length-1]; } }
/// <summary>
/// Gets the number of items in the array.
/// </summary>
public int Length { get { return items.Length; } }
/// <summary>
/// Number of items constructor.
/// </summary>
/// <param name="len">Number of items</param>
public DoubleArray(int len)
{
items = new double[len];
}
public double this[int index]
{
get { return items[index]; }
set { items[index] = value; }
}
public bool IsReadOnly
{
get { return items.IsReadOnly; }
}
public bool IsFixedSize
{
get { return items.IsFixedSize; }
}
public void CopyTo(Array array, int index)
{
items.CopyTo(array, index);
}
public IEnumerator GetEnumerator()
{
return items.GetEnumerator();
}
public object SyncRoot
{
get { return items.SyncRoot; }
}
public bool IsSynchronized
{
get { return items.IsSynchronized; }
}
object ICloneable.Clone()
{
return items.Clone();
}
#region ICollection and IList members implementation
// hides this members from intellisense, see: http://stackoverflow.com/questions/10110205/how-does-selectedlistviewitemcollection-implement-ilist-but-not-have-add
int ICollection.Count
{
get { return items.Length; }
}
int IList.Add(object value)
{
throw new NotImplementedException();
}
bool IList.Contains(object value)
{
throw new NotImplementedException();
}
void IList.Clear()
{
throw new NotImplementedException();
}
int IList.IndexOf(object value)
{
throw new NotImplementedException();
}
void IList.Insert(int index, object value)
{
throw new NotImplementedException();
}
void IList.Remove(object value)
{
throw new NotImplementedException();
}
void IList.RemoveAt(int index)
{
throw new NotImplementedException();
}
object IList.this[int index]
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
#endregion
}
Cant you use LINQ and just call
array.Last()
? (.NET 3.5 and above and "using System.Linq;")
.NET 2 Solution: (will fire IndexOutOfRange exc. in case of Count == 0)
public class MyList<T> : List<T>
{
public T Last
{
get
{
return this[this.Count - 1];
}
}
}
Since you can't Linq use, extension methods or other just add Utility class with a static method :
public static class ArrayUtility
{
public static double Last(double[] items)
{
return items[items.Length -1]);
}
}
Otherwise if you don't have to use an array, just use List<double>
If you go using List<double>. calling Add(YourNewDouble) will make it.
If you want Queue or Stack behavior. Net has classes for that : Queue<T> , Stack.
Here is a solution that satisfies me. C# 3.0 Extensions can be used in .NET 2.0 simply adding this code:
#if NET20
namespace System.Runtime.CompilerServices
{
[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
public class ExtensionAttribute : Attribute
{
}
}
#endif
Afterwards you can use the following extension method (and many others):
public static class DoubleArrayExtension
{
// This is the extension method.
// The first parameter takes the "this" modifier
// and specifies the type for which the method is defined.
public static double Last(this double[] items)
{
return items[items.Length - 1];
}
}
Thanks for all your hints and suggestions guys!
use class List or you need realize same functional
if List is not suitable use static methos Array.Resize(param) and Array.Copy(param)
Add using System.Linq; on the top of your file to be able to use Linq expressions in your code. items.Last() will return the last array item.
Here is a complete Linq methods list

Make our own List<string, string, string>

Can we make our own List<string, string, string> in C#.NET? I need to make a list having 3 different strings as a single element in the list.
You can certainly create your own class called List with three generic type parameters. I would strongly discourage you from doing so though. It would confuse the heck out of anyone using your code.
Instead, either use List<Tuple<string, string, string>> (if you're using .NET 4, anyway) or (preferrably) create your own class to encapsulate those three strings in a meaningful way, then use List<YourNewClass>.
Creating your own class will make it much clearer when you're writing and reading the code - by giving names to the three different strings involved, everyone will know what they're meant to mean. You can also give more behaviour to the class as and when you need to.
You can use a Tuple to achieve that.
For example:
var list = new List<Tuple<string,string,string>>();
to iterate over the values you may want to do a simple:
list.ForEach(x=>{
//x is a Tuple
});
or to find some specific tupple, you may want to do the folowing:
var list = new List<Tuple<string,string,string>>{
new Tuple<string,string,string>("Hello", "Holla", "Ciao"),
new Tuple<string,string,string>("Buy", "--", "Ciao")
};
list.Where(x=>x.Item2 == "--");
This will return the last Tuple.
You can use a list of tuples. Like so:
List<Tuple<string, string, string>>
Maybe something like this:
var ls= new List<Tuple<string,string,string>>();
I recommend this solution
public class MyCustomClass
{
public string MyString1 { get; set; }
public string MyString2 { get; set; }
public string MyString3 { get; set; }
}
class MyApp
{
public MyApp()
{
List<MyCustomClass> customList = new List<MyCustomClass>();
customList.Add(new MyCustomClass
{
MyString1 = "Hello",
MyString2 = "Every",
MyString3 = "Body",
});
}
}
For example:
var list = new List<Tuple<string, string, string>>();
var tuple = Tuple.Create("a", "b", "c");
list.Add(tuple);
For more information, look in MSDN.
How about making a List<Tuple<string, string, string>> ?
A better idea might be though, if each of the strings has a specific meaning, to put them all into a class and then create a List of that.
Anyone tried dynamic ?
var list = new List<dynamic>();
list.Add(new { Name = "SampleN", Address = "SampleA", Email = "SampleE" });
var name = list[0].Name;
No, sadly this does't work. The best you can do is to create a List of Lists, or utilise some form of implementation of the IDictionary interface.
Although, that said, if you have three items of data which belong together in this manner, it's probably worthwhile creating a class to contain them.
That would then give you the opportunity to pass a List around your application and assign meaningful names to each data item. Never underestimate the power of readability six months down the line.
You may define a List and implement the needed interfaces(such as IList). Codes blow.
public class List<T1, T2, T3> : IList
{
#region IList Members
public int Add(object value)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public bool Contains(object value)
{
throw new NotImplementedException();
}
public int IndexOf(object value)
{
throw new NotImplementedException();
}
public void Insert(int index, object value)
{
throw new NotImplementedException();
}
public bool IsFixedSize
{
get { throw new NotImplementedException(); }
}
public bool IsReadOnly
{
get { throw new NotImplementedException(); }
}
public void Remove(object value)
{
throw new NotImplementedException();
}
public void RemoveAt(int index)
{
throw new NotImplementedException();
}
public object this[int index]
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
#endregion
#region ICollection Members
public void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public int Count
{
get { throw new NotImplementedException(); }
}
public bool IsSynchronized
{
get { throw new NotImplementedException(); }
}
public object SyncRoot
{
get { throw new NotImplementedException(); }
}
#endregion
#region IEnumerable Members
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
#endregion
}
However, List<Tuple<string,string,string>> is recommended.
public class Listt< T, T1, T2>
{
public Listt()
{
}
public void Add(T item, T1 item1, T2 item3)
{
}
}
public partial class MyApp : Window
{
public MyApp()
{
InitializeComponent();
Listt<string, string, string> customList = new Listt<string, string, string>();
customList.Add("we","are","here");
}
}

Cast issues between generic list and CollectionDataContract

I have the following collection contract defined:
[CollectionDataContract(Name = "Centres")]
public class Centres : List<Centre>
{}
and the following operation contract defined to return this collection
public Model.Centres GetCentres()
{
List<Centre> allCentres = (from c in Model.Centre.GetCentres()
where c.Visible == true
select c).ToList();
return allCentres
}
But when I run the code I receive an ExplicitCastException. So as far as I can see I'm trying to cast a list of centres (List) into my collection 'Centres' which itself derives from List. Is this possible or by deriving a new object am I creating a new type of list that won't work in this way.
My current work around for this problem is to declare a new instance of Centres and copy all centres into it using a foreach.
The problem is Centres "is a" List<Centre>, List<Centre> is not a Centres.
Despite Centres having no implementation it is still a sub-class of List<Centre>, you could extend your Centres class to have an implicit conversion operator or, perhaps add a constructor to Centres that takes a List<Centre> as a parameter.
Try changing Centres to somthing like ...
[CollectionDataContract(Name = "Centres")]
public class Centres : List<Centre>
{
public static implicit operator Centres(List<Centre> l)
{
Centres newCentres = new Centres();
newCentres.AddRange(l);
return newCentres;
}
}
Then it will allow implicit conversion from List<Centre>.
What you are trying wont work.
If possible you should consider refactoring Centres to a has a List<Centre> more than is a relationship or at least define a constructor that takes an IEnumerable<Centre>
This way you would be able to write:
Centres allCentres = new Centres(from c in Model.Centres.GetCentres()
where c.Visible == true
select c);
Of course it all depends on your specific situation where this might not be a valid solution.
What you can do is create your own implementation of the IList<T> interface that wraps an IList.
It takes more code, but will not be as slow as to copy all the objects:
[CollectionDataContract(Name = "Centres")]
public class Centres : IList<Centre>
{
private IList<Centre> _inner;
private IList<Centre> Inner
{
get
{
if (_inner == null)
_inner = new List<Centre>();
return _inner;
}
}
public Centres(List<Centre> items)
{
_inner = items;
}
#region IList<Centre> Members
public int IndexOf(Centre item)
{
return Inner.IndexOf(item);
}
public void Insert(int index, Centre item)
{
Inner.Insert(index, item);
}
public void RemoveAt(int index)
{
Inner.RemoveAt(index);
}
public Centre this[int index]
{
get
{
return Inner[index];
}
set
{
Inner[index] = value;
}
}
#endregion
#region ICollection<Centre> Members
public void Add(Centre item)
{
Inner.Add(item);
}
public void Clear()
{
Inner.Clear();
}
public bool Contains(Centre item)
{
return Inner.Contains(item);
}
public void CopyTo(Centre[] array, int arrayIndex)
{
Inner.CopyTo(array, arrayIndex);
}
public int Count
{
get { return Inner.Count; }
}
public bool IsReadOnly
{
get { return Inner.IsReadOnly; }
}
public bool Remove(Centre item)
{
return Inner.Remove(item);
}
#endregion
#region IEnumerable<Centre> Members
public IEnumerator<Centre> GetEnumerator()
{
return Inner.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return Inner.GetEnumerator();
}
#endregion
}

In C# 4.0 why can't an out parameter in a method be covariant?

Given this magical interface:
public interface IHat<out TRabbit>
{
TRabbit Take();
}
And this class hierarchy:
public class Rabbit { }
public class WhiteRabbit : Rabbit { }
I can now compile this:
IHat<WhiteRabbit> hat1 = null;
IHat<Rabbit> hat2 = hat1;
Which is great. But what if I define the interface differently:
public interface IHat<out TRabbit>
{
bool Take(out TRabbit r);
}
I'm indicating that the hat might be empty, using a separate boolean return value (the previous version would perhaps have returned a null rabbit from an empty hat). But I'm still only outputting a rabbit, so not doing anything logically different to the previous version.
The C# 4.0 compiler in the CTP gives an error in the interface definition - it requires 'out' method parameters to be of an invariant type. Is there a hard-and-fast reason why this isn't allowed, or is it something that might be addressed in a future version?
Interesting. However, at the CLI level there is no such thing as "out" - only "ref"; there is an attribute that helps compilers (for definite assignment) that says "you don't need to pass it in".
Maybe this restriction is because the CLI doesn't have "out", only "ref".
Although it's a bit of a hassle, you can use a covariance wrapper:
public class CovariantListWrapper<TOut, TIn> : IList<TOut> where TIn : TOut
{
IList<TIn> list;
public CovariantListWrapper(IList<TIn> list)
{
this.list = list;
}
public int IndexOf(TOut item)
{
// (not covariant but permitted)
return item is TIn ? list.IndexOf((TIn)item) : -1;
}
public TOut this[int index]
{
get { return list[index]; }
set { throw new InvalidOperationException(); }
}
public bool Contains(TOut item)
{
// (not covariant but permitted)
return item is TIn && list.Contains((TIn)item);
}
public void CopyTo(TOut[] array, int arrayIndex)
{
foreach (TOut t in this)
array[arrayIndex++] = t;
}
public int Count { get { return list.Count; } }
public bool IsReadOnly { get { return true; } }
public IEnumerator<TOut> GetEnumerator()
{
foreach (TIn t in list)
yield return t;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Insert(int index, TOut item) { throw new InvalidOperationException(); }
public void RemoveAt(int index) { throw new InvalidOperationException(); }
public void Add(TOut item) { throw new InvalidOperationException(); }
public void Clear() { throw new InvalidOperationException(); }
public bool Remove(TOut item) { throw new InvalidOperationException(); }
}
This lets you keep the collection as it was originally typed and refer to it covariantly without creating a detached copy, so that updates to the original are seen in the covariant use. Example:
class CovarianceWrapperExample
{
class Person { }
class Employee : Person { }
void ProcessPeople(IList<Person> people) { /* ... */ }
void Foo()
{
List<Employee> employees = new List<Employee>();
// cannot do:
ProcessPeople(employees);
// can do:
ProcessPeople(new CovariantListWrapper<Person, Employee>(employees));
}
}

Categories

Resources