I'm looking to create named functions: objects that act as Func, but also have a string field containing a human-interpreted name.
The natural approach would be to make a class NamedFunc<T0,T1> : Func<T0,T1> { string name; } but unfortunately Func is not a class. So I'm looking for a workaround.
The end goal is that I have a function which DoMethod(MyObject victim, Func<T,T> op) and inside DoMethod I would need an alphanumeric representation of op (for caching and compatibility reasons). Currently I use op.toString().hashCode().toString() but I'd like something more meaningful, so that I can actually see which file belongs to sum, square, etc. instead of just seeing 8202589252, 58809258520, etc.
For example, I want to pass to DoMethod something along the lines of NewFunc<double,double> square = new NewFunc<double,double>(x=>x*x , "square"); and then when calling DoMethod(victim, square) DoMethod would somehow be able to recover that this function's string is "square" instead of "Func<double,double> x => x * x". At the same time, I want people to be able to just use regular Func as an input as well (without overloading the method).
Is there any feasible way to do this? Or am I looking for something impossible?
Although as you said, you can't use inheritance since Func is not a class, you can still use composition:
public class NamedFunc<T, R> {
public string Name { get; }
public Func<T, R> Invoke { get; }
public NamedFunc(Func<T, R> function, string name) {
Name = name;
Invoke = function;
}
public static implicit operator Func<T, R>(NamedFunc<T, R> namedFunc)
=> namedFunc.Invoke;
}
And you will be able to do what you want:
NamedFunc<double,double> square = new NamedFunc<double,double>(x=>x*x , "square");
To get its name, simply do square.Name. To call it, simply do square.Invoke(someNumber).
Related
I wish in my class to return a list from a dictionary but allow custom sorting using pre-written comparison methods. In my original java code that I'm converting from, I created compare methods using Google Guava Ordering in my class and then had a single method called the following passing in one of the public comparator methods, kind of declared like this:
public List<Word> getWords(Comparator c) { }
I'm trying to recreate this in C# but I can't figure out how. Essentially in the code below you can see there are three versions for each type of sort, and in addition I end up creating two lists for every return value which seems a bit wasteful.
I looked at creating delegates but got a bit lost, then figured I could create an IComparable, but then saw IComparator and then saw Sort method takes a Comparator.
Can somebody point me in the direction of converting this into a single sort 'GetWords' in the best way, allowing clients to call the GetWords retrieving a sorted list from a pre-supplied set of ordering.
public partial class WordTable
{
private Dictionary<string, Word> words;
public WordTable()
{
//for testing
words = new Dictionary<string, Word>();
words.Add("B", new Word("B", WordTypes.Adjective));
words.Add("A", new Word("A", WordTypes.Noun));
words.Add("D", new Word("D", WordTypes.Verb));
}
public List<Word> GetWords()
{
return words.Values.ToList();
}
public List<Word> GetWordsByName()
{
List<Word> list = words.Values.ToList<Word>();
return list.OrderBy(word => word.Name).ToList();
}
public List<Word> GetWordsByType()
{
List<Word> list = words.Values.ToList<Word>();
return list.OrderBy(word => word.Type).ToList();
}
}
I think you are looking for predicates.
Effectively, you want a predefined set of predicates (one for ByName, one for ByType), and you pass this predicate into the GetWords function.
There are two approaches you can use.
IComparer
This is more closely related to your past Java experience.
The official way is to use IComparer<T> (link).
Similar to your Comparator in the Java example, this enables you to create different sorting methods which all implement the IComparer<Word> interface, and then you can dynamically choose your sorting method.
As a simple example:
public class WordNameComparer : IComparer<Word>
{
public int Compare(Word word1, Word word2)
{
return word1.Name.CompareTo(word2.Name);
}
}
And then you can do:
public List<Word> GetWords(IComparer<Word> comparer)
{
return words.Values.OrderBy(x => x, comparer).ToList();
}
Which you can call by doing:
var table = new WordTable();
List<Word> sortedWords = table.GetWords(new WordNameComparer());
And of course you change the sorting logic by passing a different IComparer<Word>.
Func parameters
From experience, this is a much preferred approach due to LINQ's enhanced readability and low implementation cost.
Looking at your last two methods, you should see that the only variable part is the lambda method that you use to order the data. You can of course turn this variably into a method parameter:
public List<Word> GetWordsBy<T>(Func<Word,T> orderByPredicate)
{
return words.Values.OrderBy(orderBy).ToList();
}
Because the OrderBy predicate uses a generic parameter for the selected property (e.g. sorting on a string field? an int field? ...), you have to make this method generic, but you don't need to explicitly use the generic parameter when you call the method. For example:
var sortedWordsByName = table.GetWordsBy(w => w.Name);
var sortedWordsByLength = table.GetWordsBy(w => w.Name.Length);
var sortedWordsByType = table.GetWordsBy(w => w.Type);
Note that if you select a class, not a value type, that you will either still have to create and pass an IComparer<> for this class, or the class itself must implement IComparable<> so it can be sorted the way you want it to be.
You can introduce ascending/descending ordering:
public List<Word> GetWordsBy<T>(Func<Word,T> orderByPredicate, bool sortAscending = true)
{
return sortAscending
? words.Values.OrderBy(orderBy).ToList()
? words.Values.OrderByDescending(orderBy).ToList();
}
Update
I was trying to do it with delegates, but avoiding the caller having to roll their own lambda statement and use predefined ones.
You can simply wrap your method with some predefined options:
public List<Word> GetWordsBy<T>(Func<Word,T> orderByPredicate)
{
return words.Values.OrderBy(orderBy).ToList();
}
public List<Word> GetWordsByName()
{
return GetWordsBy(w => w.Name);
}
This way, your external callers don't need to use the lambda if they don't want to; but you still retain the benefits of having reusable code inside your class.
There are many ways to do this. I prefer creating preset methods for readability's sake, but you could instead have an enum which you then map to the correct Func. Or you could create some static preset lambdas which the external caller can reference. Or... The world is your oyster :-)
I hope this works, or even compiles.
class WordTable
{
public List<Word> GetWords(IComparer<Word> comparer)
{
return words.Values.OrderBy(x => x, comparer).ToList();
}
}
class WordsByNameAndThenTypeComparer : IComparer<Word>
{
public override int Compare(Word x, Word y)
{
int byName = x.Name.CompareTo(y.Name);
return byName != 0 ? byName : x.Type.CompareTo(y.Type);
}
}
Usage:
WordTable wt = new WordTable();
List<Words> words = wt.GetWords(new WordsByNameAndThenTypeComparer());
How to set nested property with autofixture (it's readonly)? Something like this:
var result =
fixture.Build<X>()
.With(x => x.First.Second.Third, "value")
.Create();
If I understand the question correctly, I'll assume that we have classes like these:
public class X
{
public X(One first, string foo)
{
First = first;
Foo = foo;
}
public One First { get; }
public string Foo { get; }
}
public class One
{
public One(Two second, int bar)
{
Second = second;
Bar = bar;
}
public Two Second { get; }
public int Bar { get; }
}
public class Two
{
public Two(string third, bool baz)
{
Third = third;
Baz = baz;
}
public string Third { get; }
public bool Baz { get; }
}
Specifically, I've added the properties Foo, Bar, and Baz to each of those classes to emphasise that while one may be interested in setting x.First.Second.Third to a specific value, one would still be interested in having all other properties populated by AutoFixture.
As a general observation, once you start working with immutable values, this is where a language like C# starts to reveal its limitations. While possible, it goes against the grain of the language.
There's plenty of other advantages to writing code with immutable data, but it gets tedious in C#. That's one of the reasons I finally gave up on C# and moved on to F# and Haskell. While this is a bit of a digression, I mention this to explicitly communicate that I think that using read-only properties is a fine design decision, but that it comes with some known problems.
In general, when working with immutable values, particularly in testing, it's a good idea to add copy-and-update methods to each immutable class, starting with X:
public X WithFirst(One newFirst)
{
return new X(newFirst, this.Foo);
}
On One:
public One WithSecond(Two newSecond)
{
return new One(newSecond, this.Bar);
}
and on Two:
public Two WithThird(string newThird)
{
return new Two(newThird, this.Baz);
}
This enables you to use Fixture's Get extension method to produce an X value with a particular First.Second.Third value, but where all other values are populated freely by AutoFixture.
The following test passes:
[Fact]
public void BuildWithThird()
{
var fixture = new Fixture();
var actual =
fixture.Get((X x, One first, Two second) =>
x.WithFirst(first.WithSecond(second.WithThird("ploeh"))));
Assert.Equal("ploeh", actual.First.Second.Third);
Assert.NotNull(actual.Foo);
Assert.NotEqual(default(int), actual.First.Bar);
Assert.NotEqual(default(bool), actual.First.Second.Baz);
}
This uses an overload to Fixture.Get that takes a delegate with three input values. All those values are populated by AutoFixture, and you can then nest the copy-and-update methods using x, first, and second.
The assertions show that not only does actual.First.Second.Third have the expected value, but all other properties are populated as well.
Lenses
You may think that it seems redundant that you have to ask AutoFixture for the first and second values, since x should already contain those. Instead, you may want to be able to just 'reach into' First.Second.Third without having to deal with all of those intermediary values.
This is possible using lenses.
A lens is a construct with the origin in category theory, and used in some programming languages (most notably Haskell). Functional programming is all about immutable values, but even with functional languages with first-class support for immutable data, deeply nested immutable records are awkward when you just need to update a single datum.
I don't intend to turn this answer into a lenses tutorial, so if you really want to understand what's going on, search for a lenses tutorial in your favourite functional programming language.
In short, though, you can define a lens in C# like this:
public class Lens<T, V>
{
public Lens(Func<T, V> getter, Func<V, T, T> setter)
{
Getter = getter;
Setter = setter;
}
internal Func<T, V> Getter { get; }
internal Func<V, T, T> Setter { get; }
}
A lens is a pair of functions. The Getter returns the value of a property, given a 'full' object. The Setter is a function that takes a value, and an old object, and returns a new object with the property changed to the value.
You can define a set of functions that operate on lenses:
public static class Lens
{
public static V Get<T, V>(this Lens<T, V> lens, T item)
{
return lens.Getter(item);
}
public static T Set<T, V>(this Lens<T, V> lens, T item, V value)
{
return lens.Setter(value, item);
}
public static Lens<T, V> Compose<T, U, V>(
this Lens<T, U> lens1,
Lens<U, V> lens2)
{
return new Lens<T, V>(
x => lens2.Get(lens1.Get(x)),
(v, x) => lens1.Set(x, lens2.Set(lens1.Get(x), v)));
}
}
Set and Get simply enables you to get the value of a property, or to set a property to a particular value. The interesting function here is Compose, which enables you to compose a lens from T to U with a lens from U to V.
This works best if you have static lenses defined for each class, for example for X:
public static Lens<X, One> FirstLens =
new Lens<X, One>(x => x.First, (f, x) => x.WithFirst(f));
One:
public static Lens<One, Two> SecondLens =
new Lens<One, Two>(o => o.Second, (s, o) => o.WithSecond(s));
Two:
public static Lens<Two, string> ThirdLens =
new Lens<Two, string>(t => t.Third, (s, t) => t.WithThird(s));
This is boilerplate code, but it's straightforward once you get the hang of it. Even in Haskell it's boilerplate, but it can be automated with Template Haskell.
This enables you to write the test using a composed lens:
[Fact]
public void BuildWithLenses()
{
var fixture = new Fixture();
var actual = fixture.Get((X x) =>
X.FirstLens.Compose(One.SecondLens).Compose(Two.ThirdLens).Set(x, "ploeh"));
Assert.Equal("ploeh", actual.First.Second.Third);
Assert.NotNull(actual.Foo);
Assert.NotEqual(default(int), actual.First.Bar);
Assert.NotEqual(default(bool), actual.First.Second.Baz);
}
You take X.FirstLens, which is a lens from X to One and first compose it with One.SecondLens, which is a lens from One to Two. The result so far is a lens from X to Two.
Since this is a Fluent Inteface, you can keep going and compose this lens with Two.ThirdLens, which is a lens from Two to string. The final, composed lens is a lens from X to string.
You can then use the Set extension method to set this lens on x to "ploeh". The assertions are the same as above, and the test still passes.
The lens composition looks verbose, but that's mainly an artefact of C# limited support for custom operators. In Haskell, a similar composition would literally look like first.second.third, where first, second, and third are lenses.
I've got somebody's F# library with a type in it:
module HisModule
type hisType {
a : float;
b : float;
c : float;
}
I'm using it in C#, and I would like to add a "ToString()" method to it, in order to facilitate debugging.
But the following doesn't seem to work:
public static class MyExtensions
{
public static string ToString(this HisModule.hisType h)
{
return String.Format("a={0},b={1},c={2}", h.a, h.b, h.c);
}
}
....
var h = new hisType();
Console.WriteLine(h.ToString()); // prints "HisModule+hisType"
Any ideas why not?
As others have pointed out, the ToString on object will always be a better match than your extension method. You should probably change the signature of your extension method; changing the name is probably the right way to go.
Moreover: you said that the purpose of this thing was to facilitate debugging. Overriding ToString might be the wrong thing to do there; ToString might be used for something other than debugging. I would be inclined to make my own specially-named method whose name clearly reflects the purpose of the method.
If you are creating a new type and want to have special display behaviour in the debugger, the easiest thing to do is to use the Debugger Display Attributes.
If you want to get really fancy to display a complex data structure in an interesting way, consider writing a Debugger Visualizer.
The answer to your question is "yes". Your sample does not succeed, however, because method resolution succeeds when it finds object.ToString(), so the compiler never looks for extension methods. Try it with a different name:
public static class MyExtensions
{
public static string Foo(this HisModule.hisType h)
{
return String.Format("a={0},b={1},c={2}", h.a, h.b, h.c);
}
}
....
var h = new hisType();
Console.WriteLine(h.Foo());
I think you can not do that, as ToString() is always there, in any object of CLR world.
Check out Eric Lippert answer.
You could create a wrapper type (with an implicit conversion) that overrides ToString.
class MyType {
private readonly hisType _hisType;
private MyType(hisType hisType) {
_hisType = hisType;
}
public static implicit operator MyType(hisType hisType) {
return new MyType(hisType);
}
public override string ToString() {
return String.Format("a={0},b={1},c={2}", _hisType.a, _hisType.b, _hisType.c);
}
}
hisType y;
MyType x = y;
I am working on rewriting my fluent interface for my IoC class library, and when I refactored some code in order to share some common functionality through a base class, I hit upon a snag.
Note: This is something I want to do, not something I have to do. If I have to make do with a different syntax, I will, but if anyone has an idea on how to make my code compile the way I want it, it would be most welcome.
I want some extension methods to be available for a specific base-class, and these methods should be generic, with one generic type, related to an argument to the method, but the methods should also return a specific type related to the particular descendant they're invoked upon.
Better with a code example than the above description methinks.
Here's a simple and complete example of what doesn't work:
using System;
namespace ConsoleApplication16
{
public class ParameterizedRegistrationBase { }
public class ConcreteTypeRegistration : ParameterizedRegistrationBase
{
public void SomethingConcrete() { }
}
public class DelegateRegistration : ParameterizedRegistrationBase
{
public void SomethingDelegated() { }
}
public static class Extensions
{
public static ParameterizedRegistrationBase Parameter<T>(
this ParameterizedRegistrationBase p, string name, T value)
{
return p;
}
}
class Program
{
static void Main(string[] args)
{
ConcreteTypeRegistration ct = new ConcreteTypeRegistration();
ct
.Parameter<int>("age", 20)
.SomethingConcrete(); // <-- this is not available
DelegateRegistration del = new DelegateRegistration();
del
.Parameter<int>("age", 20)
.SomethingDelegated(); // <-- neither is this
}
}
}
If you compile this, you'll get:
'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingConcrete' and no extension method 'SomethingConcrete'...
'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingDelegated' and no extension method 'SomethingDelegated'...
What I want is for the extension method (Parameter<T>) to be able to be invoked on both ConcreteTypeRegistration and DelegateRegistration, and in both cases the return type should match the type the extension was invoked on.
The problem is as follows:
I would like to write:
ct.Parameter<string>("name", "Lasse")
^------^
notice only one generic argument
but also that Parameter<T> returns an object of the same type it was invoked on, which means:
ct.Parameter<string>("name", "Lasse").SomethingConcrete();
^ ^-------+-------^
| |
+---------------------------------------------+
.SomethingConcrete comes from the object in "ct"
which in this case is of type ConcreteTypeRegistration
Is there any way I can trick the compiler into making this leap for me?
If I add two generic type arguments to the Parameter method, type inference forces me to either provide both, or none, which means this:
public static TReg Parameter<TReg, T>(
this TReg p, string name, T value)
where TReg : ParameterizedRegistrationBase
gives me this:
Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments
Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments
Which is just as bad.
I can easily restructure the classes, or even make the methods non-extension-methods by introducing them into the hierarchy, but my question is if I can avoid having to duplicate the methods for the two descendants, and in some way declare them only once, for the base class.
Let me rephrase that. Is there a way to change the classes in the first code example above, so that the syntax in the Main-method can be kept, without duplicating the methods in question?
The code will have to be compatible with both C# 3.0 and 4.0.
Edit: The reason I'd rather not leave both generic type arguments to inference is that for some services, I want to specify a parameter value for a constructor parameter that is of one type, but pass in a value that is a descendant. For the moment, matching of specified argument values and the correct constructor to call is done using both the name and the type of the argument.
Let me give an example:
ServiceContainerBuilder.Register<ISomeService>(r => r
.From(f => f.ConcreteType<FileService>(ct => ct
.Parameter<Stream>("source", new FileStream(...)))));
^--+---^ ^---+----^
| |
| +- has to be a descendant of Stream
|
+- has to match constructor of FileService
If I leave both to type inference, the parameter type will be FileStream, not Stream.
I wanted to create an extension method that could enumerate over a list of things, and return a list of those things that were of a certain type. It would look like this:
listOfFruits.ThatAre<Banana>().Where(banana => banana.Peel != Color.Black) ...
Sadly, this is not possible. The proposed signature for this extension method would have looked like:
public static IEnumerable<TResult> ThatAre<TSource, TResult>
(this IEnumerable<TSource> source) where TResult : TSource
... and the call to ThatAre<> fails because both type arguments need to be specified, even though TSource may be inferred from the usage.
Following the advice in other answers, I created two functions: one which captures the source, and another which allows callers to express the result:
public static ThatAreWrapper<TSource> That<TSource>
(this IEnumerable<TSource> source)
{
return new ThatAreWrapper<TSource>(source);
}
public class ThatAreWrapper<TSource>
{
private readonly IEnumerable<TSource> SourceCollection;
public ThatAreWrapper(IEnumerable<TSource> source)
{
SourceCollection = source;
}
public IEnumerable<TResult> Are<TResult>() where TResult : TSource
{
foreach (var sourceItem in SourceCollection)
if (sourceItem is TResult) yield return (TResult)sourceItem;
}
}
}
This results in the following calling code:
listOfFruits.That().Are<Banana>().Where(banana => banana.Peel != Color.Black) ...
... which isn't bad.
Notice that because of the generic type constraints, the following code:
listOfFruits.That().Are<Truck>().Where(truck => truck.Horn.IsBroken) ...
will fail to compile at the Are() step, since Trucks are not Fruits. This beats the provided .OfType<> function:
listOfFruits.OfType<Truck>().Where(truck => truck.Horn.IsBroken) ...
This compiles, but always yields zero results and indeed doesn't make any sense to try. It's much nicer to let the compiler help you spot these things.
If you have only two specific types of registration (which seems to be the case in your question), you could simply implement two extension methods:
public static DelegateRegistration Parameter<T>(
this DelegateRegistration p, string name, T value);
public static ConcreteTypeRegistration Parameter<T>(
this ConcreteTypeRegistration p, string name, T value);
Then you wouldn't need to specify the type argument, so the type inference would work in the example you mentioned. Note that you can implement both of the extension methods just by delegation to a single generic extension method with two type parameters (the one in your question).
In general, C# doesn't support anything like o.Foo<int, ?>(..) to infer only the second type parameter (it would be nice feature - F# has it and it's quite useful :-)). You could probably implement a workaround that would allow you to write this (basically, by separating the call into two method calls, to get two places where the type inferrence can be applied):
FooTrick<int>().Apply(); // where Apply is a generic method
Here is a pseudo-code to demonstrate the structure:
// in the original object
FooImmediateWrapper<T> FooTrick<T>() {
return new FooImmediateWrapper<T> { InvokeOn = this; }
}
// in the FooImmediateWrapper<T> class
(...) Apply<R>(arguments) {
this.InvokeOn.Foo<T, R>(arguments);
}
Why don't you specify zero type parameters? Both can be inferred in your sample. If this is not an acceptable solution for you, I'm frequently encountering this problem too and there's no easy way to solve the problem "infer only one type parameter". So I'll go with the duplicate methods.
What about the following:
Use the definition you provide:
public static TReg Parameter<TReg, T>(
this TReg p, string name, T value)
where TReg : ParameterizedRegistrationBase
Then cast the parameter so the inference engine gets the right type:
ServiceContainerBuilder.Register<ISomeService>(r => r
.From(f => f.ConcreteType<FileService>(ct => ct
.Parameter("source", (Stream)new FileStream(...)))));
I think you need to split the two type parameters between two different expressions; make the explicit one be part of the type of a parameter to the extension method, so inference can then pick it up.
Suppose you declared a wrapper class:
public class TypedValue<TValue>
{
public TypedValue(TValue value)
{
Value = value;
}
public TValue Value { get; private set; }
}
Then your extension method as:
public static class Extensions
{
public static TReg Parameter<TValue, TReg>(
this TReg p, string name, TypedValue<TValue> value)
where TReg : ParameterizedRegistrationBase
{
// can get at value.Value
return p;
}
}
Plus a simpler overload (the above could in fact call this one):
public static class Extensions
{
public static TReg Parameter<TValue, TReg>(
this TReg p, string name, TValue value)
where TReg : ParameterizedRegistrationBase
{
return p;
}
}
Now in the simple case where you are happy to infer the parameter value type:
ct.Parameter("name", "Lasse")
But in the case where you need to explicitly state the type, you can do so:
ct.Parameter("list", new TypedValue<IEnumerable<int>>(new List<int>()))
Looks ugly, but hopefully rarer than the simple fully-inferred kind.
Note that you could just have the no-wrapper overload and write:
ct.Parameter("list", (IEnumerable<int>)(new List<int>()))
But that of course has the disadvantage of failing at runtime if you get something wrong. Unfortunately away from my C# compiler right now, so apologies if this is way off.
I would used the solution:
public class JsonDictionary
{
public static readonly Key<int> Foo = new Key<int> { Name = "FOO" };
public static readonly Key<string> Bar = new Key<string> { Name = "BAR" };
IDictionary<string, object> _data;
public JsonDictionary()
{
_data = new Dictionary<string, object>();
}
public void Set<T>(Key<T> key, T obj)
{
_data[key.Name] = obj;
}
public T Get<T>(Key<T> key)
{
return (T)_data[key.Name];
}
public class Key<T>
{
public string Name { get; init; }
}
}
See:
C#: Exposing type safe API over heterogeneous dictionary
I have a class MyClass, and I would like to override the method ToString() of instances of List:
class MyClass
{
public string Property1 { get; set; }
public int Property2 { get; set; }
/* ... */
public override string ToString()
{
return Property1.ToString() + "-" + Property2.ToString();
}
}
I would like to have the following:
var list = new List<MyClass>
{
new MyClass { Property1 = "A", Property2 = 1 },
new MyClass { Property1 = "Z", Property2 = 2 },
};
Console.WriteLine(list.ToString()); /* prints: A-1,Z-2 */
Is it possible to do so? Or I would have to subclass List<MyClass> to override the method ToString() in my subclass? Can I solve this problem using extension methods (ie, is it possible to override a method with an extension method)?
Thanks!
Perhaps a bit off-topic, but I use a ToDelimitedString extension method which works for any IEnumerable<T>. You can (optionally) specify the delimiter to use and a delegate to perform a custom string conversion for each element:
// if you've already overridden ToString in your MyClass object...
Console.WriteLine(list.ToDelimitedString());
// if you don't have a custom ToString method in your MyClass object...
Console.WriteLine(list.ToDelimitedString(x => x.Property1 + "-" + x.Property2));
// ...
public static class MyExtensionMethods
{
public static string ToDelimitedString<T>(this IEnumerable<T> source)
{
return source.ToDelimitedString(x => x.ToString(),
CultureInfo.CurrentCulture.TextInfo.ListSeparator);
}
public static string ToDelimitedString<T>(
this IEnumerable<T> source, Func<T, string> converter)
{
return source.ToDelimitedString(converter,
CultureInfo.CurrentCulture.TextInfo.ListSeparator);
}
public static string ToDelimitedString<T>(
this IEnumerable<T> source, string separator)
{
return source.ToDelimitedString(x => x.ToString(), separator);
}
public static string ToDelimitedString<T>(this IEnumerable<T> source,
Func<T, string> converter, string separator)
{
return string.Join(separator, source.Select(converter).ToArray());
}
}
You'll need to subclass to override any method. The point of generics is to say that you want the same behaviour regardless of the type of T. If you want different behaviour for a specific type of T then you are breaking that contract and will need to write your own class:
public class MyTypeList : List<MyClass>
{
public override string ToString()
{
return ...
}
}
Edited to add:
No, you can't override a method by creating an extension, but you could create a new method with a different signature that is specific to this list type:
public static string ExtendedToString(this List<MyClass> list)
{
return ....
}
Used with
List<MyClass> myClassList = new List<MyClass>
string output = myClassList.ExtendedToString();
I still think you're better off subclassing though...
You can actually use a unicode trick to allow you to define an alternate ToString method directly against your generic list.
If you enable hex character input into visual studio then you can create invisible characters by holding down the Alt key, then pressing the following on your numeric keypad + F F F 9 (now release Alt)
So we can create the following function with an invisible character placed next to its name... (yes i know its VB code, but the concept will still work work for C#)
<Extension()> _
Public Function ToString(ByVal source As Generic.List(Of Char)) As String
Return String.Join(separator:="", values:=source.ToArray)
End Function
Now in visual studio, when you access intellisense against your list, you will be able to choose between either the standard ToString or your custom function.
To enable hex character input into visual studio you may need to edit your registry
open HKEY_CURRENT_USER\Control Panel\Input Method
and create a REG_SZ called EnableHexNumpad set this to 1
You will also need to disable the & shortcuts for the File, Edit, Debug, Data menus,
In visual studio, open the tools menu, select customize, then open the commands tab, and using the modify selection button for any menu item that uses either of the ABCDEF charactes for its short cut, by removing the &
Otherwise you will end up opening popup menus, instead of typing hex characters.
If you method must be named ToString you will have to derive a class from List. You can make it a generic:
static class MyList<T> : List<T>
{
public override string ToString()
{
// ...
}
}
In this case, you would have to use MyList instead of List throughout your application if you wish to have your custom conversion.
However, if you can choose a different name for your method, you can use extension methods and achieve the same effect, with almost no modifications to your code:
You can use extension methods to make this more generic:
static class ListExtension
{
public static void ConvertToString<T>(this IEnumerable<T> items)
{
// ...
}
}
You can use it on any instance of IEnumerable<T> just as if it were an ordinary method:
List<MyClass> list = new List<MyClass> { ... };
Console.WriteLine(list.ConvertToString());
int[] array_of_ints = {1,2,3,4,5};
Console.WriteLine(array_of_ints.ConvertToString());
You would have to create your own custom class that inherits from Collection and then overwride the ToString() method of that class specifically.
No its not possible. ToString of TList will give you the string representation of the list object.
Your options are:
Derive from TList and override the .ToString() method as you mentioned. (in this example I wouldn't say its worth doing so)
Create a helper method that converts a TList list to a comma delimited string e.g. extension method (probably best suggestion)
Use a foreach statement at the Console.WriteLine stage.
Hope that helps!
Depending on the exact reason you have for wanting to override List<T>.ToString() to return something specific it might be handy to have a look at custom TypeConverter implementations.
If you simply want a List<T> of specific T to show itself a certain way as a string in locations where TypeConverters are used, like in the debugger or in string.Format("List: {0}", listVariable) type situations, this might be enough.
You might just have seen the result of ToString() being shown somewhere and wanted to change that, without knowing about the existence of TypeConverter and locations where they are used. I believe many/most/all (not sure which?) of the default TypeConverters in the .NET Framework simply use ToString() when converting any type for which they are defined for to a string.