How to create extension method on generic collection - c#

I have a list that contains FrameworkElements and I want to create an extension method called MoveToTop. All this will do is accept an item that is part of that list and move it to the beginning of the list. I know this could be accomplished without the use of an extension method, but I would like it to be implemented as an extension method.
I am having trouble trying to figure out the syntax for creating an extension method that accepts a generic parameter. I know this isn't correct, but if someone could give me an idea how how to accomplish this, I would appreciate it.
public static class Extensions
{
public static void MoveToTop(this ICollection<T> sequence)
{
//logic for moving the item goes here.
}
}

You were close, just need the <T> after the method name before the parenthesis. That's where the generic type parameter list for generic methods is placed. It declares the generic type parameters the method will accept, which then makes them available to be used in the arguments, return values, and method body.
public static class Extensions
{
public static void MoveToTop<T>(this ICollection<T> sequence)
{
//logic for moving the item goes here.
}
}

Related

Extension method for IEnumerable<T> which returns type of -this-

Like I see, most IEnumerable extensions eats IEnumerable and then vomits also IEnumerable. Is it possible to make an extension method, which can eat any IEnumerable (like List) and then return the same type - List?
For example, I want to iterate over collection, if something is wrong, I will throw exception, but if all is OK, I need to return same instance (same type).
You need to use two generic arguments:
public static TEnumerable Foo<TEnumerable, TItem>(this TEnumerable sequence)
where TEnumerable: IEnumerable<TItem>
{
return sequence;
}
Note that as a result of this change you're not going to be able to infer the generic arguments when invoking this method; you're going to have to specify them explicitly.
I don't see how doing this could be beneficial, but you can solve the generics part of the problem like this:
public static TEnumerable MyExtensionMethod<T, TEnumerable>(this TEnumerable enumerable)
where TEnumerable : IEnumerable<T>
{
...
}
However, you may find it difficult to actually implement such a thing because there is no generic way to create the TEnumerable you want to return.
For example, I want to iterate over collection, if something is wrong, I will throw exception, but if all is OK, I need to return same instance (same type).
Does the following extension method not accomplish what you really want? I don't understand why you want to return the same instance.
public static void Consume<T>(this IEnumerable<T> enumerable)
{
foreach (var item in enumerable)
{
// Do nothing
}
}

How can I override ToString() method for all IEnumerable<Int32>?

I want to override ToString() on IEnumerable<Int32>.
I was thinking to use Extension methods.
But when I do this below, it still calls the ToString() on System.Object. When I rename my method, then it calls my method.
As my extension method is in a static class, I am not able to override.
How can I achieve this so that my ToString() implementation is called when I call .ToString() on List<Int32> for example?
public static class ExtensionMethods
{
public static new string ToString(this IEnumerable<Int32> set)
{
var sb = new StringBuilder();
// Do some modifications on sb
return sb.ToString();
}
}
How can I achieve this so that my ToString() implementation is called when I call .ToString() on List for example?
You can't, basically. Extension methods are only used if no matching instance method can be found.
I suggest you give your method a different name, avoiding the problem - and the potential confusion your method would cause.
Note that even if extension methods were matched in preference to (say) methods declared on object, it would only make a difference for your own code being compiled with an appropriate using directive - not any other code which has already bound the call to the normal one.
If you can give more information about what you're trying to achieve, we may be able to help you more - but for the moment, something like ToDelimitedString (or whatever your method does) sounds like the best bet to me.
You cannot replace a method using extension methods.
Method resolution will check for a method belonging to the type, before trying to find matching extension methods.
In other words, you cannot replace ToString, but yes, you can create your own method.
Either create your own IEnumerable<T> type with an overridden ToString method, or use a different method name. Of course, using your own type will of course only work when you're actually using that type.
It's not possible to override   ToString, but you can create a wrapper, that you can call in every place, where you are using IEnumerable<Int32>
To output a collection as string I am using an extension method
 
 
public static string ToString<T>( this IEnumerable<T> messages)
{
     return ToString<T>(messages, Environment.NewLine, "" );
}
ToString<T>( this IEnumerable<T>messages, string separator, string sComment)
is described in my post 
ToString function for Generic List
See also similar Overriding ToString() of List<MyClass>
Similar function implemented as an extension method described in post:
Separator Delimited ToString for Array, List, Dictionary, Generic IEnumerable
You cannot override ToString but you can create a generic method.
This is a simple solution based on Michael Freidgeim's answer (its link is broken):
static public class Extensions {
// extension for arrays, lists, any Enumerable -> AsString
public static string AsString<T>(this IEnumerable<T> enumerable) {
var sb = new StringBuilder();
int inx = 0;
foreach (var item in enumerable) {
sb.Append($"{inx}: {item}\r\n");
inx++;
}
return sb.ToString();
}
}
Usage:
Console.WriteLine(arr.AsString());
Console.WriteLine(list.AsString());
Console.WriteLine(linqResult.AsString());

Implement same Generic Interface 2 times with different Generic parameter

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
{
...
}
}

How to Hide a member method by an Extension Method

public static class MyClass
{
public static void Add<T>(this List<T> list, T item)
{
list.Add(item);
Console.WriteLine(item.ToString());
}
}
then
List<string> list = new List<string>(){"1","2"};
list.Add("3");
But the member method would be called.
Is there anyway to call my Extension Method this way?
I don't want to call it like this:
MyClass.Add(list, item)
You can't. Instance methods always take precedence over extension methods, assuming they're applicable. Member resolution will only consider extension methods once it's failed to find a non-extension-method option.
I would suggest you simply rename your method - unless the point was to call this method transparently with existing code.
If you made it take an IList<T> instead of List<T>, you could create a wrapper type which implements IList<T> and delegates all calls onto the wrapped list, performing any extra tasks as you go. You could then also write an extension method to IList<T> which created the wrapper - which would allow for more fluent syntax in some cases. Personally I prefer the wrapper approach to deriving a new collection type, as it means you can use it with your existing collections, making the code changes potentially smaller... but it all depends on what you're trying to do.
Instance methods always take precedence over extension methods, so no.
The correct thing to do here would appear to be polymorphism - but note that List<T> doesn't provide virtual methods. Collection<T> does, though:
using System;
using System.Collections.ObjectModel;
class MyClass<T> : Collection<T> {
protected override void InsertItem(int index, T item) {
base.InsertItem(index, item);
Console.WriteLine("Added:" + item.ToString());
}
protected override void SetItem(int index, T item) {
base.SetItem(index, item);
Console.WriteLine("Set (indexer):" + item.ToString());
}
// see also ClearItems and RemoveItem
}

.NET: How to check the type within a generic typed class?

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(); }
}

Categories

Resources