I am pretty new in C# (I came from Java) and I have a doubt about the use of:
I have this class:
namespace DataModel.MaliciousCode
{
public class PagedMalicious : Shared.Paged
{
public IEnumerable<MaliciousSmall> MaliciousCode { get; set; }
}
}
As you can see this class contains only a IEnumerable<MaliciousSmall> MaliciousCode
Reading the online documentation it seems to me to understand that IEnumerable is an interface that give me an iterator on a non generic collection.
What exactly means the previous assertion?
I have MaliciousSmall that is the type of a model object in my application (an object that contains some properties that map the fields of a table on the DB)
So my doubt are:
IEnumerable<MaliciousSmall> MaliciousCode: MaliciousCode is an iterable collection of MaliciousSmall objects? So it means that it represent a collection and some provided methods to iterate on it?
If the previous assertion is true, ok MaliciousCode object is an iterable collection but IEnumerable is an interface so who implement the method to iterate on this collection (coming from Java I think that an interface is not provided of implemented methods)
Some one can help me to understand these things?
Tnx
Andrea
IEnumerable<MaliciousSmall> MaliciousCode: MaliciousCode is an iterable collection of MaliciousSmall objects? So it means that it represent a collection and some provided methods to iterate on it?
Sort of - IEnumerable<T> provides one method - GetEnumerator - which returns an IEnumerator<T>. THAT interface allows you to iterate over the collection. Pre-Linq all IEnumerable allowed you to do was use the collection in a foreach loop (or use the provided IEnumerator directly, which is rare). Linq has since defined extension methods on IEumerable<T> that allow more sophisticated queries like Select, Where, Count, etc.
If the previous assertion is true, ok MaliciousCode object is an iterable collection but IEnumerable is an interface so who implement the method to iterate on this collection (coming from Java I think that an interface is not provided of implemented methods)
Typically the implementation is provided by using an underlying collection type like List<MaliciousSmall> or MaliciousSmall[]. So the IEnumerable implementation is provided by that class. The yield keyword introduced in C# 2.0 allows you to "return" an IEnumerable<T> and let the compiler provide the actual implementation.
So in your class, you might internally implement the collection as a List<T>:
public class PagedMalicious : Shared.Paged
{
public IEnumerable<MaliciousSmall> MaliciousCode { get; set; }
public PagedMalicious()
{
MaliciousCode = new List<MaliciousSmall>();
}
// other private methods that add to MaliciousCode
}
The use of IEnumerable<T> allows you to change the internal implementation without changing the public interface.
Your property MaliciousCode, represents an object of a class that implements IEnumerable<T> interface. On it's own, IEnumerable does not really mean anything. It just provides a structure. It is user's responsibility to implement the methods that are provided with interface whatever way the see it suitable.
Edit: Here is a simple example to demonstrate:
private void Form3_Load(object sender, EventArgs e)
{
Parent parent = new Parent();
parent.Child = new List<Child>(); // -> this is where implementer is decided.
//Before this line, Child property is not instantiated and is not referring to any object.
}
public class Parent
{
public IEnumerable<Child> Child { get; set; }
}
public class Child
{
public int MyProperty { get; set; }
}
To your doubts:
Yes and Yes
The interface itself can't implement anything, but you can assign an array of MaliciousSmall or a List<MaliciousSmall>. Both of them implement IEnumerable<MaliciousSmall>
IEnumerable<T> is the equivalent of Java's Iterable<T>. Since the early versions of C# did not have generics, IEnumerable was the only iterator available at that time. You can think of it as a kind of IEnumerable<object>.
Most generic collection types implement IEnumerable<T>, including arrays. The generic variant requires the non-generic variant to be implemented, therefore most collections (generic or not) implement IEnumerable.
However, these iterators are not limited to represent collections. They provide methods that allow you to enumerate items and these methods can generate items algorithmically as well. For instance an - in theory - endless enumeration of square numbers could be provided by an enumeration without the requirement to store those numbers anywhere.
In your case the IEnumerable<MaliciousSmall> MaliciousCode property could yield MaliciousSmall objects from the DB one by one as the enumeration is being enumerated without storing them in a collection object first.
Implementing IEnumerable<T> yourself requires the implementation of the IEnumerator<T> GetEnumerator() method. It returns an enumerator object which requires the implementation of the methods bool MoveNext(), void Dispose(), void Reset() and the property T Current { get; }.
You can implement these interfaces the good old way, by writing a lot of code, or you can use C#'s iterators. Iterators use a lot of compiler magic to create enumerables and enumerators automatically behind the scenes. See: Iterators (C# and Visual Basic).
As an example of C# iterators, let's implement your example with them (I dropped the setter as it stands in the way here):
public class PagedMalicious : Shared.Paged
{
public IEnumerable<MaliciousSmall> MaliciousCode
{
get
{
using (var conn = new SqlConnection("<my server connection>")) {
var cmd = new SqlCommand("SELECT name, number FROM myTable", conn);
conn.Open();
using (var reader = cmd.ExecuteReader()) {
while (reader.Read()) {
var maliciousSmall = new MaliciousSmall {
Name = reader.GetString(0),
Number = reader.GetInt32(1)
};
yield return maliciousSmall;
}
}
}
}
}
}
Each time yield return is executed, the control is passed back to the caller and he gets the next item. The state of the getter method is kept intact and its execution is halted here until the caller continues iterating and requires the next item. When he does so, the execution resumes just after the yield return statement.
You can see from this example, that enumerations are evaluated in a lazy way. The following code sums up the numbers of the whole table. The items are never stored in a collection; they are retrieved from the DB and created as they are enumerated. This is an advantage, if you have one million records! (You would use an SQL SUM aggregate function in a productive piece of code, so.)
var pagedMalicious = new PagedMalicious();
int sum = 0;
foreach (MaliciousSmall item in pagedMalicious.MaliciousCode) {
sum += item.Number;
}
Related
I am writing a Silverlight and WCF project.
I have used the Entity Framework in Silverlight to get the data from the database, I have multiple pages where I use EF.
Now, I have more than 100 types of entity class and hence multiple known list types.
In my WCF interface I want to create one generic function where I can accept all this list types as one generic parameter.
So my WCF function should be like
public string TestBadal(List<Object> list)
{
return "test";
}
My question here is, how can I cast all the known lists to List. I am fairly new to this so any help will be much appreciated.
Thank you.
you can use T
public static List<T> o<T>(List<T> a)
{
return a = new List<T>();
}
As Sophex states you can write a generic function to process a List<> or better still an IList<> of anything.
So your example would become,
public string TestBadal<T>(IList<T> list)
{
return "test";
}
This is very generic and requires and implies little about T. This may be sufficient for the processing you want to perform but, you don't say.
In general, you should view your method signature as a promise that the caller has to make to the function. You should limit the promise to only what is required for your function to do its job. This way, the promise is easier to make and your function can get reused more with less commitment from the caller.
Your function as it stands, doesen't actually need a parameters and would be better defined as a string const but say, all you wanted to do was enumerate the items you could use,
public string TestBadal<T>(IEnumerable<T> entities)
{
foreach(T entity in entities)
{
...
}
}
If your processing is especially related to the EF nature of the data source you could do,
public string TestBadal<TEntity>(EntitySet<TEntity> entities)
where TEntity : class
{
...
}
If you need to know somthing about the type in the list then you have two sensible options.
Either you require the types to implement a certain interface, this essentialy makes your function non-generic and could be awkward with in conjunction with EF.
public string TestBadal(IEnumerable<IDefinedType> definedTypeInstances)
{
foreach(IDefinedType instance in definedTypeInstances)
{
var x = instance.SomeDefinedProperty;
}
}
Or, you can take the non generic parts of the function as a typed delegate parameter, keeping the function generic, possibly somthing like this.
public string TestBadal<T>(
IList<T> list,
Func<T, string> stringSelector)
{
var result = new StringBuilder();
for(var i = 0; i < list.Count; i++)
{
result.AppendLine(stringSelector(list[i])
}
return result.ToString();
}
You could call this function with a lambda expression somthing like this,
var result = TestBadal(entities, e => e.SomeStringProperty);
I hope this answer both gives you some ideas and illustrates my point that the right answer depends on what you want your function to achieve.
I had to implement 2 interface same time with different generic parameter as below. I get confused enough about it. I had no idea which one of them iterate itself in foreach. Now i understand first one is implicitly choosen.
I have tried new BarList().GetEnumerator() but i can not specify type parameter on method level.
Only solution i have found it that casting it to interface like(new BarList() as IEnumerable<string>)
After confusing about it enough. I just wanted to know that this design is not really good idea ? I have to avoid to implement same generic interface one more time ?
class Program
{
static void Main(string[] args)
{
foreach (var item in new BarList())
{
}
}
}
class BarList: IEnumerable<string>, IEnumerable<int>
{
public IEnumerator<int> GetEnumerator()
{
throw new NotImplementedException();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator<string> IEnumerable<string>.GetEnumerator()
{
throw new NotImplementedException();
}
}
Edit:
Let me explain why i am going in this way.
I had to Implement IPagedList<T> interface which is inherited from IList<T>. I wanted to write extension method which convert it to My view model. like below
GetAll().ToPagedList(pageindex);//which is returning IPagedList Then i wanted to use it like below;
GetAll().ToPagedList(pageindex).ToViewModel<T,TViewModel>();
For achieve this I tried to return IPagedList<ViewModel> by that extension method.In that case I have to implement IPagedList 2 times with different parameter. But this strategy made confusing things. This is reason of it.
This seems a bit confusing. Why not make it explicit what is happening by adding the enumerators as properties rather than implementing them on the class. For example,
class ProductCollection
{
public IEnumerable<int> EnumerateTheInts { get { //code to produce enumerator }}
public IEnumerable<string> EnumerateTheStringss { get { //code to produce enumerator }}
}
It isn't always bad to implement an open generic interface twice on an object. For example, IHandle could be implemented by a class which can handle two types of T. However, I would find it confusing to implement IEnumerable twice, because you might not enumerate the type you expect in a for-each or in LINQ. Same reasoning for implementing more than one indexer incidentally. The type of your indexer will determine your result, which I can testify to being extremely confusing!
The compiler is picking the IEnumerator<int> GetEnumerator method by following the rules in 8.8.4 of the C# language specification which first looks for an accessible GetEnumerator() method on the BarList type. The only one of those which is available is the one returning IEnumerator<int>.
If you had made that method use explicit interface implementation as well, then it would have gone onto the later stages of section 8.8.4, which states that if there is more than one type T such that there is an implicit conversion from the expression type (BarList here) to IEnumerable<T> then an error is produced.
I would say this is a confusing design - I would probably add properties or methods to retrieve appropriate "views" on the data.
I'd avoid it. However, it depends on your usage.
It will be okay if you just wanted to pass the instance into a function that expects a IEnumerable<string> parameter explicitely:
you won't have to cast
the function won't even 'see' the other interfaces implemented, so there isn't any confusion.
YMMV
Your current design is confusing. While you have not provided any information about the nature of the collection itself, from the name, I can assume you are supposed to iterate over a bunch of products. Perhaps, you should simply have a class of type Product with a string property and an int property and simply return an IEnumerable<Product> instead.
This way, with LINQ extension methods, you can compose the IEnumerable<T> object you actually mean with:
collection.Select(product => product.IntegerProperty)
collection.Select(product => product.StringProperty)
Of course, you can provide helper methods inside the object as well:
class ProductCollection : IEnumerable<Product> {
public IEnumerable<Product> GetEnumerator() {
// ... return Product objects here.
}
public IEnumerable<int> AsIntegerCollection() {
// yield the integer collection here
}
public IEnumerable<string> AsStringCollection() {
// yield the string collection here
}
}
What are these collections of string and ints? I suppose they mean something in relation with the Product (for example Name, Id, etc...) so I would rather do something like this:
class ProductCollection : IEnumerable<Product>
{
public IEnumerator<Product> GetEnumerator()
{
...
}
public IEnumerator<string> ProductNames // a helper to enumerate product names
{
...
}
public IEnumerator<int> ProductIds // a helper to enumerate product ids
{
...
}
}
OK.
I have a class MyClass and another class that is based on List. Let's call it MyCollection.
Now when someone types:
MyCollection coll = new MyCollection();
...
coll.Find(...)
They are acting on the entire collection. I want to apply some filtering - behind the scenes - so that if they write the above code, what actually executes is something like...
coll.Where(x=>x.CanSeeThis).Find(...)
What do I need to write in the definition of the MyCollection class to make this work?
Can I make this work?
You probably want to write a wrapper class that implements IList or ICollection, using a regular List internally. This wrapper class would then proxy all method calls to the internal list, applying the filter as required.
You´ve already mentioned you´ve got your own collection, probably derived from List right?
Then you´ll need to create your own method for finding:
public class MyList<T> : System.Collections.Generic.List<T>
{
public IEnumerable<T> MyFind(Predicate<T> match)
{
return this.Where(x => x.CanSeeThis).ToList().Find(match);
}
}
This unfortunatly is needed because you cannot override the Find method on List directly. You can however use the 'new' keyword to specify that If you´ve got a reference to the instance of MyList it will use that implementation of find, like below:
public new IEnumerable<T> Find(Predicate<T> match)
{
return this.Where(x => x.CanSeeThis).ToList().Find(match);
}
However the above example will yield:
MyCollection<int> collection = new ...
collection.Find(myPredicate); // <= Will use YOUR Find-method
List<int> baseTypeCollection = collection; // The above instantiated
baseTypeCollection.Find(myPredicate); // Will use List<T>.Find!
So it´s better you make you´re own method.
I have followed the suggestions from this post to try and get Distinct() working in my code but I am still having issues. Here are the two objects I am working with:
public class InvoiceItem : IEqualityComparer<InvoiceItem>
{
public InvoiceItem(string userName, string invoiceNumber, string invoiceAmount)
{
this.UserName = userName;
this.InvoiceNumber= invoiceNumber;
this.InvoiceAmount= invoiceAmount;
}
public string UserName { get; set; }
public string InvoiceNumber { get; set; }
public double InvoiceAmount { get; set; }
public bool Equals(InvoiceItem left, InvoiceItem right)
{
if ((object)left.InvoiceNumber == null && (object)right.InvoiceNumber == null) { return true; }
if ((object)left.InvoiceNumber == null || (object)right.InvoiceNumber == null) { return false; }
return left.InvoiceNumber == right.InvoiceNumber;
}
public int GetHashCode(InvoiceItem item)
{
return item.InvoiceNumber == null ? 0 : item.InvoiceNumber.GetHashCode();
}
}
public class InvoiceItems : List<InvoiceItem>{ }
My goal is to populate an InvoiceItems object (we will call it aBunchOfInvoiceItems) with a couple thousand InvoiceItem objects and then do:
InvoiceItems distinctItems = aBunchOfInvoiceItems.Distinct();
When I set this code up and run it, I get an error that says
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'InvoiceReader.Form1.InvoiceItems'. An explicit conversion exists (are you missing a cast?)
I don't understand how to fix this. Should I be taking a different approach? Any suggestions are greatly appreciated.
Distinct returns a generic IEnumerable<T>. It does not return an InvoiceItems instance. In fact, behind the curtains it returns a proxy object that implements an iterator that is only accessed on demand (i.e. as you iterate over it).
You can explicitly coerce it into a List<> by calling .ToList(). You still need to convert it to your custom list type, though. The easiest way is probably to have an appropriate constructor, and calling that:
public class InvoiceItems : List<InvoiceItem> {
public InvoiceItems() { }
// Copy constructor
public InvoiceItems(IEnumerable<InvoiceItems> other) : base(other) { }
}
// …
InvoiceItems distinctItems = new InvoiceItems(aBunchOfInvoiceItems.Distinct());
Konrad Rudolph's answer should tackle your compilation problems. There is one another important semantic correctness issue here that has been missed: none of your equality-logic is actually going to be used.
When a comparer is not provided to Distinct, it uses EqualityComparer<T>.Default. This is going to try to use the IEquatable<T> interface, and if this is missing, falls back on the plain old Equals(object other) method declared on object. For hashing, it will use the GetHashCode() method, also declared on object. Since the interface hasn't been implemented by your type, and none of the aforementioned methods have been overriden, there's a big problem: Distinct will just fall back on reference-equality, which is not what you want.
Tthe IEqualityComparer<T> interface is typically used when one wants to write an equality-comparer that is decoupled from the type itself. On the other hand, when a type wants to be able to compare an instance of itself with another; it typically implements IEquatable<T>. I suggest one of:
Get InvoiceItem to implement IEquatable<InvoiceItem> instead.
Move the comparison logic to a separate InvoiceItemComparer : IEqualityComparer<InvoiceItem> type, and then call invoiceItems.Distinct(new InvoiceItemComparer());
If you want a quick hack with your existing code, you can do invoiceItems.Distinct(new InvoiceItem());
Quite simply, aBunchOfInvoiceItems.Distinct() returns an IEnumerable<InvoiceItem> and you are trying to assign that to something that is not an IEnumerable<InvoiceItem>.
However, the base class of InvoiceItems has a constructor that takes such an object, so you can use this:
public class InvoiceItems : List<InvoiceItem>
{
public InvoiceItems(IEnumerable<InvoiceItem> items)
base(items){}
}
Then you can use:
InvoiceItems distinctItems = new InvoiceItems(aBunchOfInvoiceItems.Distinct());
As is though, I don't see much benefit in deriving from List<InvoiceItem> so I would probably lean more toward:
List<InvoiceItem> distinctItems = aBunchOfInvoiceItems.Distinct().ToList();
The error has everything to do with your class InvoiceItems, which inherits from List<InvoiceItem>.
Distinct returns an IEnumerable<InvoiceItem>: InvoiceItems is a very specific type of IEnumerable<InvoiceItem>, but any IEnumerable<InvoiceItem> is not necessarily an InvoiceItems.
One solution could be to use an implicit conversion operator, if that's what you wanted to do: Doh, totally forgot you can't convert to/from interfaces (thanks Saed)
public class InvoiceItems : List<InvoiceItem>
{
public InvoiceItems(IEnumerable<InvoiceItem> items) : base(items) { }
}
Other things to note:
Inheriting from List<T> is usually bad. Implement IList<T> instead.
Using a list throws away one of the big benefits of LINQ, which is lazy evaluation. Be sure that prefetching the results is actually what you want to do.
Aside from the custom class vs IEnumerable issue that the other answers deal with, there is one major problem with your code. Your class implements IEqualityComparer instead of IEquatable. When you use Distinct, the items being filtered must either implement IEquatable themselves, or you must use the overload that takes an IEqualityComparer parameter. As it stands now, your call to Distinct will not filter the items according to the IEqualityComparer Equals and GetHashCode methods you provided.
IEqualityComparer should be implemented by another class than the one being compared. If a class knows how to compare itself, like your InvoiceItem class, it should implement IEquatable.
How do I get the type of a generic typed class within the class?
An example:
I build a generic typed collection implementing ICollection< T>. Within I have methods like
public void Add(T item){
...
}
public void Add(IEnumerable<T> enumItems){
...
}
How can I ask within the method for the given type T?
The reason for my question is: If object is used as T the collection uses Add(object item) instead of Add(IEnumerable<object> enumItems) even if the parameter is IEnumerable. So in the first case it would add the whole enumerable collection as one object instead of multiple objects of the enumerable collection.
So i need something like
if (T is object) {
// Check for IEnumerable
}
but of course that cannot work in C#. Suggestions?
Thank you very much!
Michael
You can use: typeof(T)
if (typeof(T) == typeof(object) ) {
// Check for IEnumerable
}
Personally, I would side step the issue by renaming the IEnumerable<T> method to AddRange. This avoids such issues, and is consistent with existing APIs such as List<T>.AddRange.
It also keeps things clean when the T you want to add implements IEnumerable<T> (rare, I'll admit).
If you want to use the is operator in a generic class/method you have to limit T to a reference type:
public void MyMethod<T>(T theItem) where T : class
{
if (theItem is IEnumerable) { DoStuff(); }
}