Let's say I declare this string array:
string[] arr = new string[]{"foo", "bar"};
How is that the LINQ extension methods are being attached to it?
I know the LINQ extension methods are declared in System.Linq.Enumerable, but the extension methods act upon IEnumerable<TSource>:
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
Since arr isn't a generic, and to my knowledge doesn't implement IEnumerable<T> how is the Where() extension method attached to it?
From the documentation:
Starting with the .NET Framework 2.0, the Array class implements the System.Collections.Generic.IList<T>, System.Collections.Generic.ICollection<T>, and System.Collections.Generic.IEnumerable<T> generic interfaces. The implementations are provided to arrays at run time, and therefore are not visible to the documentation build tools. As a result, the generic interfaces do not appear in the declaration syntax for the Array class, and there are no reference topics for interface members that are accessible only by casting an array to the generic interface type (explicit interface implementations). The key thing to be aware of when you cast an array to one of these interfaces is that members which add, insert, or remove elements throw NotSupportedException.
Therefore, since T[] does implement IEnumerable<T>, and the compiler is fully aware of that fact, it is perfectly legal to use extensions methods defined on IEnumerable<T>s on arrays.
Related
I'm looking for good tutorials on how to create LINQ accessors/APIs to my business classes. So that someone could eventually enter something like this in a program--
var potentialCustomers = from people in county
where people.NumberOfCats > 2
select people
I've used LINQ often enough with the .Net collections, but have never done it before on my own classes. Is it just a matter of implementing IEnumerable, or are there additional steps needed?
LINQ is an interesting beast.
Immediately IEnumerable<T> comes to mind when discussing LINQ. It seems that IEnumerable<T> is LINQ, but it is not. IEnumerable<T> is one implementation of the LINQ methods that allow LINQ queries to be written against objects that implement IEnumerable<T>.
Another implementation is IObservable<T> which powers the Microsoft's Reactive Extensions. This is a set of extensions that allow LINQ queries to be written against events (or streams of data). Nothing to do with IEnumerable<T>.
LINQ also can be written directly in your objects - it doesn't have to be extension methods at all.
For example, define classes A and B like so:
public class A
{
public B Select(Func<A, B> selector)
{
return selector(this);
}
}
public class B
{
public B(A a) { }
}
Now I can write this code:
B query =
from x in a
select new B(x);
It's LINQ, Jim, but not as we know it.
All of the LINQ operators can be defined this way. So long as the compiler gets to see methods with the right signature you're golden.
Having said this LINQ queries feel natural when working with a series of values - and hence this is why IEnumerable<T> and IObservable<T> are good examples of LINQ in action. But it certainly is possible to define LINQ against any type you like just by implementing the right methods.
You just need to implement IEnumerable interface in your class and then you can use LINQ.
Because LINQ is a set of extensions for IEnumerable objects
Imagine i have an extension method that operates of an interface of abstract objects:
public static void BlowTheirWhoHoovers(this ICollection<Image> source)
{
...
}
This extension knows how to blow the who hoovers of a list of images.
Note:
it's a list of Images, which is abstract. As long as the lists contain anything that descends from Image (e.g. Bitmap, Metafile, PngImage) the extension can handle it
source list can by any kind of list as long as it exposes ICollection
since source list is going to potentially have items added or removed, it is ICollection rather than IEnumeration (IEnumeration doesn't support modifying the list)
That's all well and good, except it doesn't work, the extension method is not found:
Collection<Bitmap> whoHonkers = new Collection<Bitmap>();
whoHonkers.BlowTheirWhoHoovers();
i assume this fails because:
Visual Studio doesn't think Collection implements ICollection<T>
Visual Studio doesn't think Bitmap descends from Image
Now i can change my extension:
public static void BlowTheirWhoHoovers(this Collection<Bitmap> source)
{
...
}
which does compile:
except it's no longer useful (it requires Collection, and it requires Bitmap), e.g. it fails to work on anything except Collection<T>:
List<Bitmap> whoHonkers = new List<Bitmap>();
whoHonkers.BlowTheirWhoHoovers();
It also fails on anything that it's Bitmap:
List<Metafile> whoHonkers = new List<Metafile>();
whoHonkers.BlowTheirWhoHoovers();
or
List<PngImage> whoHonkers = new List<PngImage>();
whoHonkers.BlowTheirWhoHoovers();
How can i apply an extension to anything that is:
ICollection<Image>
?
i can't force anyone to change their declaration, e.g.:
List<Bitmap>
to
Collection<Image>
Update:
Possible avenues of solution exploration:
finding the syntax that allows extensions on things that the compiler should be able to do
manually casting the list; doing the compiler's job for it
Update#2:
i could have simplified some of the distractions around ICollection, and made it IEnumerable (since it's a hypothetical example i can make up whatever i want). But the screenshots already show Collection, so i'm going to leave it as it is.
Update#3:
As foson pointed out, changing it to IEnumerable allows a way to cheat the answer. So it definitely should stay as ICollection.
Sounds like a covarient problem.
If you change the signature to
public static void BlowTheirWhoHoovers(this IEnumerable<Image> source)
you should be able to do it in .NET 4 (not SL).
The problem with varience is that if you passed into the method an ICollection<JpegImage>, the method itself wouldn't know that it could only add JpegImages and not Bitmaps, defeating type saftey. Therefore the compiler does not let you do it. IEnumerable's type parameter is covarient, as seen by the out keyword, while ICollection's type parameter is not (since it is both in return positions and method parameter positions in the ICollection interface)
public interface IEnumerable<out T>
http://msdn.microsoft.com/en-us/library/dd799517.aspx
I'll start by saying that I'm working off the assumption that static array initializers are turned into private nested classes by the compiler, usually with names like __StaticArrayInitTypeSize=12. As I understand it, having read this extremely informative article, these private classes are value types, and they aren't tagged with the CompilerGeneratedAttribute class.
I'm working on a project that needs to process certain types and ignore others.
I have to be able to process custom struct types, which, like the generated static array initializer classes, are value types. I must ignore the generated static array initializer classes. I also must ignore enumerations and delegates.
I'm pulling these classes with Linq, like so:
var typesToProcess = allTypes.Where(type => !type.IsEnum &&
!type.IsArray &&
!type.IsSubclassOf(typeof(Delegate)));
I'm fairly sure that the IsArray property isn't what I think it is. At any rate, the generated static array initializer class still shows up in the typesToProcess Enumerable.
Has anyone else dealt with this? How can I discern the difference between a custom struct and a generated static array initializer class? I could hack it by doing a string comparison of the type name against __StaticArrayInitTypeSize, but is there a cleaner solution?
Well, having just tried it myself with the C# 4 compiler, I got an internal class called <PrivateImplementationDetails>{D1E23401-19BC-4B4E-8CC5-2C6DDEE7B97C} containing a private nested struct called __StaticArrayInitTypeSize=12.
The class contained an internal static field of the struct type called $$method0x6000001-1. The field itself was decorated with CompilerGeneratedAttribute.
The problem is that all of this is implementation-specific. It could change in future releases, or it could be different from earlier releases too.
Any member name containing <, > or = is an "unspeakable" name which will have been generated by the compiler, so you can view that as a sort of implicit CompilerGenerated, if that's any use. (There are any number of other uses for such generated types though.)
I am really really really new to all of this, and most of it is unexplored territory. Today I needed to create an anonymous class and put it to a list. I was trying to find how I can make a list of anonymous types, and found that I should make an extension method. I also already figured out an extension method should be in a static class. But what I haven't figured out yet is if there is some pattern that I should use? For now, I have made a static class in my App_Code folder named ExtensionMethods, but have no idea if I should put extension methods of all kinds of types in this class, or if I should make separate classes etc.
To my knowledge you can not implement extension methods for anonymous classes. And this makes sense as really and truly if the class has some semantics it should be made a named class.
To create a list of anonymous classes use this method:
public static List<T> CreateListFromType<T>(T anonType){
return new List<T>();
}
To use this method to create a list, do something like:
var list = CreateListFromType(new {A = default(int), B = default(int)});
Extension method is nothing more than easier-to-read static helper/utility methods. The way you organize them is the same principal as how you organize your normal classes. If you think those should stays together, then try to give them a meaningful, general enough name as the class name. Once you found your class name cannot include what that method doing, then you know that method should belongs to other places.
Firstly extension methods are normal static methods declared like this -
void MyExtension(this MyTarget target, int myparam){ ..
After this the C# compiler adds some syntactic sugar letting you call this method as
target.MyExtension(myparam);
The compiler will replace all these calls with
MyStaticClass.MyExtension(target, myparam);
The important thing is that an extension method is a normal static method. You should follow following guidelines while creating them -
Try to group extension methods for each target class in a separate static class and name it appropriately as Extensions.
Create a new namespace in your application for Extension methods such as MyAppExtensions and keep your static classes inside this namespace. This will keep the coder from misunderstanding them as Extension method and accidentally using them as instance methods.
Make these naming conventions for namespaces and static classes of Extension methods as a standard in the team.
In your extension method check if the first parameter is null and take appropriate action. If you do not then it will be possible to call the method with target being null and may result in unexpected behavior. If the first parameter is allowed to be null then document it clearly.
Consciously decide if it is correct to create and extension method or instance method will be better.
Be careful that the extension method names do not clash with instance method names or other existing extension method names for this class. Following point 1, 2 and 3 will help you achieve this.
I learnt these from Jon Skeet's C# In Depth. You should read it too.
This is how you create a list of an anonymous class.
var anonList = new[]{
new {Foo = "foo", Bar = 2},
new { Foo = "bar", Bar = 3},
}.ToList();
It has nothing to do with writing extension methods.
Edit:
In fact you will have a hard time to use extension methods to create anonymous types since anonymous types can not be used as method parameters or return type.
Edit2:
If you want to convert a list of anonymous types to a list of specific types you can use Select:
class MyClass
{
public string Prop1 {get;set;}
public int Prop2 {get;set;}
}
List<MyClass> myList = anonList.Select(x => new MyClass(){Prop1 = Foo, Prop2 = Bar}).ToList();
I use to put anonymous to DataTable. Due to it's limitation, DataTable provide more functionality such as serialization.
Caveat emptor, I'm new to Linq To SQL.
I am knocking up a prototype to convert an existing application to use Linq To SQL for its model (it's an MVVM app). Since the app exists, I can not change its data model.
The database includes information on events; these are either advertising events or prize events. As such, the data model includes a table (Event) with two associated tables (AdvertisingEvent and PrizeEvent). In my old C# code, I had a base class (Event) with two subclasses (AdvertisingEvent and PrizeEvent) and used a factory method to create the appropriate flavour.
This can not be done under Linq to SQL, it does not support this inheritance strategy.
What I was thinking of doing is creating an interface (IEvent) to includes the base, shared functionality (for example, a property "Description' which is implemented in each subclass). I thought I'd then add a propery to the superclass, for example SharedStuff, that would either return an AdvertisingEvent or PrizeEvent as a IEvent. From WPF I could then bind to MyEvent.SharedStuff.Description.
Does this make sense? Is there a better way to do this?
BTW: I'd rather not have to move to Linq to Entities.
You could always use interface inheritance to accomplish this. Instead of working with subclasses, have your IEvent interface, with the IPrizeEvent and IAdvertisingEvent interfaces deriving from that.
Then, work in terms of the interfaces.
You could then have separate implementations that don't derive from each other, but implement the appropriate interfaces.
Also, the nice side effect of working with interface inheritance in LINQ-to-SQL is if you have methods that operate on IQueryable<T> where the constraint on T is IEvent, you can do something like this:
// Get an IQueryable<AdvertisingEvent>
IQueryable<AdvertisingEvent> events = ...;
// A function to work on anything of type IEvent.
static IQueryable<T> FilteredEvents<T>(this IQueryable<T> query,
string description)
where T : class, IEvent
{
// Return the filtered event.
return query.Where(e => e.Description == description);
}
And then make the call like this:
events = events.FilteredEvents("my description");