I have code that I want to make the following changes:
How do I override ToString()? It says: A static member ...ToString(System.Collections.Generic.List)' cannot be marked as override, virtual, or abstract.
How do I make it generic?
public static override string ToString(this List<int> list) {
string output = "";
list.ForEach(item => output += item.ToString() + "," );
return output;
}
Thanks!
You cannot use extension methods to override an existing method.
From the spec http://msdn.microsoft.com/en-us/library/bb383977.aspx
"You can use extension methods to extend a class or interface, but not to override them. An extension method with the same name and signature as an interface or class method will never be called. At compile time, extension methods always have lower priority than instance methods defined in the type itself."
If you want to override ToString(), you would need to inherit from List<T> rather than try to extend it. You have already seen that you cannot mark the static extension method as override, and overload resolution will always go for the member method over an extension method if it is available. Your options are
Inherit and override
Change your extension method's name to something else ToSpecialString()
Call the method directly using the class name MyExtensions.ToString(myList);
What are you trying to achieve? Often I want to output the contents of a list, so I created the following extension method:
public static string Join(this IEnumerable<string> strings, string seperator)
{
return string.Join(seperator, strings.ToArray());
}
It is then consumed like this
var output = list.Select(a.ToString()).Join(",");
EDIT: To make it easier to use for non string lists, here is another variation of above
public static String Join<T>(this IEnumerable<T> enumerable, string seperator)
{
var nullRepresentation = "";
var enumerableAsStrings = enumerable.Select(a => a == null ? nullRepresentation : a.ToString()).ToArray();
return string.Join(seperator, enumerableAsStrings);
}
public static String Join<T>(this IEnumerable<T> enumerable)
{
return enumerable.Join(",");
}
Now you can consume it like this
int[] list = {1,2,3,4};
Console.WriteLine(list.Join()); // 1,2,3,4
Console.WriteLine(list.Join(", ")); // 1, 2, 3, 4
Console.WriteLine(list.Select(a=>a+".0").Join()); // 1.0, 2.0, 3.0, 4.0
You can only override a method if you inherit the base class.
What I would advocate is calling your extension method .ToCsv().
Related
I'm trying to learn a mobile development framework called Xamarin that uses C#, which I am a beginner at as well. I was following a tutorial when I came across the following code:
public static class PhonewordTranslator
{
public static string ToNumber(string raw)
{
if (string.IsNullOrWhiteSpace(raw))
{
return "";
}
else
{
raw = raw.ToUpper();
}
var newNumber = new StringBuilder();
foreach (var c in raw)
{
if (" -0123456789".Contains(c))
{
newNumber.Append(c);
}
else
{
var result = TranslateToNumber(c);
if (result != null)
{
newNumber.Append(result);
}
}
}
return newNumber.ToString();
}
static bool Contains (this string keyString, char c)
{
return keyString.IndexOf(c) >= 0;
}
static int? TranslateToNumber(char c)
{
if ("ABC".Contains(c))
return 2;
else if ("DEF".Contains(c))
return 3;
else if ("GHI".Contains(c))
return 4;
else if ("JKL".Contains(c))
return 5;
else if ("MNO".Contains(c))
return 6;
else if ("PQRS".Contains(c))
return 7;
else if ("TUV".Contains(c))
return 8;
else if ("WXYZ".Contains(c))
return 9;
return null;
}
Why am I allowed to pass in a single parameter to the Contains() method even though it clearly has two parameters. What is the purpose of this?
The Contains() method is whats known as an extension method. You can find more information about them here.
In your code Contains method is defined as Extension Method.
So what are Extension Methods
Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type.
And how they work?
Extension methods are defined as static methods but are called by using instance method syntax. Their first parameter specifies which type the method operates on, and the parameter is preceded by the this modifier.
In your code you invoke the extension method with instance method syntax. However, the intermediate language (IL) generated by the compiler translates your code into a call on the static method.
Lets understand this with an example.
As you all know if we convert an object which is null to string by calling ToString method then it throws NullReferenceException. Though I can call Convert.ToString() method which doesn't throw exception for null value. But what if I want to stick ToString method like syntax. So before calling ToString method on any object that need to be converted to stringvalue, First i need to check for null and then convert it to string value. But it is time consuming and i have to write code for it.
To overcome this i have created a ExtensionMethod named as ToStringNullSafe. It is going to first check for null value of object. If it has null value then it will convert it to an Empty String otherwise converts object value to a string value.
This is the definition of the my Extension method
public static string ToStringNullSafe(this object obj)
{
return (obj ?? string.Empty).ToString();
}
And this is the calling syntax
DataRow dr = dataTable.Rows[0];
string firstName = dr["firstName"].ToStringNullSafe();
One thing need to consider while creating a ExtensionMethod is that ExtentionMethod name should differ from the method present in .Net framework. Like we have ToString method for string conversion. So i can't create a extension method with this name.
What if i create an extension method with name as of .Net framework method name then there will not be compiler errors but your created ExtensionMethod will not be called. Suppose if i create an extension method by defining its name as ToString then compiler will not invoke my extension method. It will invoke ToString method provided by .Net framework.
In visual studio a Down Arrow sign appears for ExtensionMethos
Extension Methods can be placed in separate class like i have an Extension Method to convert a DataTable to string[][] array in a separate class.
namespace myProject.Common
{
public static class ExtensionMethods
{
public static object ToStringArray(this DataTable dt, params string[] columns)
{
//AsEnumerable is also a Extension Method provided by .Net framework.
return dt.AsEnumerable().Select(x => columns.Select(c => x[c].ToStringNullSafe()).ToArray()).ToArray();
}
}
public static string ToStringNullSafe(this object obj)
{
return (obj ?? string.Empty).ToString();
}
}
To use this ExtensionMethod in my project, i have to add an using statement first
using myProject.Common;
then i can call this method as follow:
var dataTableData = dataTable.ToStringArray("firstName", "LastName", "Age", "Email");
Another syntax of calling extension method is;
var dataTableData = ExtensionMethods.ToStringArray(dataTable,"firstName", "LastName", "Age", "Email");
Further Reading:
Extension
Methods
Creating an extension method for ToString?
Advantages of Extension Methods
Disadvantages of extension methods
What is the difference between generic method and generic extension method and extension method?
Generic method by MSDN.
A generic method is a method that is declared with type parameters
static void Swap<T>(ref T lhs, ref T rhs)
{
T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}
This method swaps the references between lhs (left-hand-side) and rhs (right-hand-side). Because we only want to swap the references and don't care about what the underlying types of the references are, we can declare the method as a generic method with type parameter T. This means it can be of any type. This saves us from having to write multiple Swap methods.
string s1 = "hello";
string s2 = "world";
Swap(ref s1, ref s2);
int i1 = 5;
int i2 = 12;
Swap(ref i1, ref i2);
While the example could be written using object types as Swap method parameters, this would cause an unnecessary overhead with value types known as boxing.
Extension method by MSDN
Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type.
Let's say we want to extend the existing string class to contain a method for counting words in the string.
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' },
StringSplitOptions.RemoveEmptyEntries).Length;
}
Now we can count words from any string object.
string s = "Hello Extension Methods";
int i = s.WordCount();
This is especially useful for adding features (methods) to existing classes which you do not have access to (from third party assembly, for example).
Generic extension methods are simply a mix of the previous two concepts.
generic method is called just like regular method, with the difference it can be used for different types by specifying generic type.
someObject.GenericMethodFromSameClass<String>();
generic extension method and extension method are similar to each other in a sense that they can be called on objects they extend. Difference between them is the same as difference between regular method and generic method.
someObject.ExtensionMethodFromOtherClass();
someObject.GenericExtensionMethodFromOtherClass<String>();
• Extension Method:
With extension method can add some extra method to specified type.
For create extension method
Definition class with public static attribute.
Definition method in class with public static attribute.
For first parameter of method defined extension method .place before this parameter keyword this.
public static class TestExtensionClass
{
public static string TestExtinsionMethod(this string password)
{
string encriptedPassword="";
byte[] ASCIIValues = Encoding.ASCII.GetBytes(password);
foreach (byte b in ASCIIValues)
{
encriptedPassword += b.ToString();
}
return encriptedPassword;
}
}
In other classes call extension method.
private void CallExtensionMethod()
{
string s = "123";
s.TestExtinsionMethod();
}
• Generic Method:
With generic method you can define output type in runtime.
For create extension method
Definition class.
Definition method. Before name of method place T.
After name of method place <**T>**.
public T TestCastTo<T>(object obj)
{
return (T)obj;
}
In other classes call Generic method.
public static T TestCastTo<T>(this object obj)
{
return (T)obj;
}
• Generic Extension Method:
• With combine properties Extension Method and Generic Method you can gain a Generic Extension Method.
public static T TestCastTo<T>(this object obj)
{
return (T)obj;
}
in other class call generic extension method
private void CallGenericExtensionMethod()
{
string s = "123";
int i = s.TestCastTo<int>();
}
Methods can be generic or nongeneric, for example:
public void Foo() { } // Non-Generic Method
public void Foo<T>(T value) { } // Generic Method
Extension methods are methods used to extend the behavior of types without modifying the type itself. Say you want the String type to have a Reverse method, you could define an extension method on the String type, like this:
public static class ExtMethods
{
public static string Reverse(this string s) // Non-Generic Extension Method
{
// code to reverse string
}
}
Extension methods must be declared static and within a static class, also its first parameter must have this before the type it extends.
Likewise, extension methods can be generic:
public static class ExtMethods
{
public static Foo<T>(this T obj) // Generic extension method
{
}
}
So, a Generic Extension Method is just an extension method that happens to be generic.
Consider the following method example:
public static string[] ParseOptions()
{
return Environment.GetCommandLineArgs();
}
What would I have to do to create an extension that would make ParseOptions() return all command line arguments in lower case?
I would like to be able to use the extension as follows:
var argArray = ParseOptions().MyExtToLower();
Note: I'm asking this to better understand how to create an extension for a method. I'm not actually interested in getting lower case command line arguments this way.
public static string[] MyExtToLower(this string[] source)
{
for (int i = 0; i < source.Length; i++)
{
source[i] = source[i].ToLower();
}
return source;
}
Notice the this keyword in the parameter list. That is what makes it possible to call the method like this:
var argArray = ParseOptions().MyExtToLower();
To be clear, you're not actually adding an extension to a method here. What you are doing is adding an extension to the type that the method returns.
You seem to be talking about Fluent Interfaces. Look at this example - http://blog.raffaeu.com/archive/2010/06/26/how-to-write-fluent-interface-with-c-and-lambda.aspx
Or, you can create extension methods on the type you are returning ( in your case, string[] ) to get the method chaining - http://msdn.microsoft.com/en-us/library/bb383977.aspx
For the syntax you describe you would have to extend String[] or possibly IEnumerable<String> the following way:
public static class MyExtensions {
public static String[] MyExtToLower(this String[] strings) {
return strings.Select(s => s.toLower()).ToArray();
}
public static IEnumerable<String> MyExtToLower(this IEnumerable<String> strings) {
return strings.Select(s => s.toLower());
}
}
You don't create extension of methods, you create methods which extend objects' capabilities. Those methods must be static and part of a static class. They must have one parameter marked with the this keyword to indicate which object you want to extend. In your case, you must write something like:
// the class must be static, I usually declare a class reserved for extension method.
// I mark it as partial so that I can put every method in the same file where I use it.
public static partial class Extension {
// This is the extension method; it must be static. Note the 'this' keyword before
// the first parameter: it tells the compiler extends the string[] type.
public static MyExtToLower( this string[ ] args ) {
// your code
}
}
Note that you cannot override instance method. Altough you can have a method with the same signature as an instance method that method will be never called due to the way the compiler binds to.
I have tried this:
public static class ListHelper
{
public static string ToString<T>(this IList<String> list)
{
return string.Join(", ", list.ToArray());
}
public static string ToString<T>(this String[] array)
{
return string.Join(", ", array);
}
}
But it does not work, both for string[] and List<string>. Maybe I need some special annotations?
Extension methods are only checked if there are no applicable candidate methods that match. In the case of a call to ToString() there will always be an applicable candidate method, namely, the ToString() on object. The purpose of extension methods is to extend the set of methods available on a type, not to override existing methods; that's why they're called "extension methods". If you want to override an existing method then you'll have to make an overriding method.
It sounds like you want to replace what files.ToString() returns. You will not be able to do that without writing a custom class to assign files as (i.e. inherit from List and override ToString().)
First, get rid of the generic type (<T>), you're not using it. Next, you will need to rename the extension method because calling files.ToString()will just call the List's ToString method.
This does what you're looking for.
static class Program
{
static void Main()
{
var list = new List<string> { {"a"}, {"b"}, {"c"} };
string str = list.ToStringExtended();
}
}
public static class ListHelper
{
public static string ToStringExtended(this IList<String> list)
{
return string.Join(", ", list.ToArray());
}
}
Simply you Shouldn't use the name ToString for the Extension method as it will never be called because that method already exist and you shouldn't use T as its useless there.
For example i tried this and again it returned same thing:
Console.WriteLine(lst.ToString<int>());
output:
shekhar, shekhar, shekhar, shekhar
so this time i used int and it still ran because that T has no use other then changing the Method Prototype.
So simply why are you using ToString Literal as Method name, as it already exist and you can't override it in a Extension method, this is the reason you had to use that T to make it generic. Use some different name like
public static string ToMyString(this IList<String> list)
That way you wouldn't have to use generic as it useless there and you could simply call it as always.
That said your code is working for me. here is what i tried (in LINQPAD):
void Main()
{
List<string> lst = new List<string>();
lst.Add("shekhar");
lst.Add("shekhar");
lst.Add("shekhar");
lst.Add("shekhar");
lst.ToString<string>().Dump();
}
public static class ListHelper
{
public static string ToString<T>(this IList<String> list)
{
return string.Join(", ", list.ToArray());
}
public static string ToString<T>(this String[] array)
{
return string.Join(", ", array);
}
}
And the output was shekhar, shekhar, shekhar, shekhar
Since you have specified that T in ToString<T> you will need to mention a Type like string or int while calling the ToString method.
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.