Why is my extension method not working? - c#

I have an extension method
public static class DbMigratorExtensions
{
public static IEnumerable<string> DoCoolStuff(this DbMigrator dbMigrator, string[] first, string[] second)
{
// ...
}
}
and I'm trying to use it like
DbMigrator.DoCoolStuff
but I get the
'DbMigrator' does not contain a definition for ...
I have followed all the bullet points on
Why is my Extension Method not showing up in my test class?
Also I will note that VS recognizes
DbMigratorExtensions.DoCoolStuff
so I'm not sure why it isn't working as an extension method.

Extension methods work on object instances, not types.
So you need to change
DbMigrator.DoCoolStuff(...);
to
var migrator = new DbMigrator();
var stringList = migrator.DoCoolStuff(...);
If DoCoolStuff() doesn't need an instance, it should not be an extension method.

If what you want is a static extension method, C# does not currently support this. You can only make non-static extension methods. This will probably change at some point.

Related

Extension method on string[] to lowercase all elements?

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.

using Linq with dynamic c# objects

When i run the following code :
var aList = new List<string>{"a", "b", "c"};
dynamic a = aList.Where(item => item.StartsWith("a"));
dynamic b = a.Count();
Microsoft.CSharp.RuntimeBinder.RunTimeBinderException raises.
But when I write a code snippet like this:
public interface IInterface
{
}
public class InterfaceImplementor:IInterface
{
public int ID = 10;
public static IInterface Execute()
{
return new InterfaceImplementor();
}
}
public class MyClass
{
public static void Main()
{
dynamic x = InterfaceImplementor.Execute();
Console.WriteLine(x.ID);
}
}
it's work.
Why first code snippet doesn't work?
Because the Count method is an extension method on IEnumerable<T> (Once you call Where, you don't have a list anymore, but an IEnumerable<T>). Extension methods don't work with dynamic types (at least in C#4.0).
Dynamic lookup will not be able to find extension methods. Whether extension methods apply or not depends on the static context of the call (i.e. which using clauses occur), and this context information is not currently kept as part of the payload.
Will the dynamic keyword in C#4 support extension methods?
Extension methods are syntactic sugar that allow you to call a static method as if it was a real method. The compiler uses imported namespaces to resolve the correct extension method and that is information the runtime doesn't have. You can still use the extension methods, you just have to call them directly in their static method form like below.
var aList = new List<string>{"a", "b", "c"};
dynamic a = aList.Where(item => item.StartsWith("a"));
dynamic b = Enumerable.Count(a);

Overload generic List's Add with extension method

I would like to overload a generic list's Add method so I can use collection initializations like:
var x = new List<Tuple<string>> { { "1", "2" }, { "1", "2" } };
(Where Tuple is a simple custom implementation of a binary tuple.)
However, I created an extension method, put a using directive in the cs file, and still get the "No overload for method 'Add' takes 2 arguments"-error.
Is it not possible to do (with an extension method)?
Extension method code:
namespace ExtensionMethods {
public static class Extensions{
public static void Add<T>(this List<Tuple<T>> self, T value1, T value2) {
self.Add(new Tuple<T> { value1, value2 });
}
}
}
It is not possible via extension methods. In order to make this syntax working you have to create your own collection class which will have void Add(T value1, T value2) signature.
P.S.: What you've done is not overload and there is no way to overload anything in existing class.
UPDATE: Looks like my first sentence should be: "It is not possible via extension methods in C#"
In C# 6.0[0] Microsoft allows the use of extensions methods in collection initializers. hurray :)
And since this isn't a .NET Framework or CLR change, but a compiler change, this feature can be used with .NET 4.0.
So the following is now valid C# code. (Tested in Visual Studio 2015 RC)
class Program
{
static void Main(string[] args)
{
var x = new List<Tuple<string,string>> { { "1", "2" }, { "1", "2" } };
}
}
public static class Extensions
{
public static void Add<T1,T2>(this List<Tuple<T1,T2>> self, T1 value1, T2 value2)
{
self.Add(Tuple.Create( value1, value2 ));
}
}
C# 6 Features [0]
You cannot implement constructors using extension methods.Extension method is nothing but a static method which takes in an instance of an object. Hence you need to have an instance first to be able to pass to it.
But you can just use AddRange() of the List to initialise your list.
Extension methods can't overload any method defined on their target type simply because they are not members of the target type. Extension methods do not ADD anything to their target types. They are just compiler magic that allow them to be called as if they were methods defined on their target type. In reality, they are defined in a separate static type, hence they can't overload any method on their target type.
Behind the scenes, the compiler replaces any calls to your extension method with a call to Extensions.
It looks like you are trying to make C# behave like Ruby and initialize an array of objects by passing a set of values, or at least imitate the behavior of dictionary initialization.
Unfortunately you can't do that without actually overloading List<>.
Collection initialization is just another bit of compiler magic that tries to find an Add method with as many arguments as there are items in the argument list. If it were otherwise you could define a conversion operator to convert a list to your Tuple type.
Why don't you just use the built-in object initializers? You'll just have to write a bit more code

What do you mean by "extension methods" in C#?

Can anyone else explain this, (beginners approach). Thanks..
Extension Methods are just static methods in static classes that behaves like they were defined in other class.
In the first parameter before the type goes the keyword this wich indicates that is an extension method.
Example:
public static class Extensions
{
public static object ExtensionMethodForStrings( this string s, object otherParameter)
{
//....
return //whatever you want to return or not
}
}
This is an extension method on System.String that takes two parameters:
- string s : This is the instance variable
- object otherParameter: You can have as many as you want including none
You can call this method in two ways:
Static way:
string s = "Your string";
object o = new object(); // or whatever you want
object result = Extensions.ExtensionMethodForStrings(s,o);
Extension Method way
string s = "Your string";
object o = new object(); // or whatever you want
object result = s.ExtensionMethodForStrings(o);
In the second case it works as if the type string has an instance method called ExtensionMethodForStrings. Actually for the compiler the are equivalent.
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. For client code written in C# and Visual Basic, there is no apparent difference between calling an extension method and the methods that are actually defined in a type.
The C# article on Extension Methods.
An extension method is a static method in a static class whose first parameter is preceded by the keyword this.
The C# compiler has some syntactic sugar that can convert a call of x.Foo(bar) to SomeExtension.Foo(x, bar). This is used extensively by LINQ (Take, Skip, Where, Select, etc.) but you can also write your own extension methods if you wish.
This question includes lots of examples of useful extension methods:
What are your favorite extension methods for C#? (codeplex.com/extensionoverflow)
An extension method is a method that behaves (somewhat) like it is a member of a class, but it is not a member of that class. It can be called on members of that class, but has no reference to the internals of the class.
Extension methods are static methods, and must be members of a static class.
public static class StringExtensions
{
public static string HtmlEncode(this string dataString)
{
return HttpServerUtility.HtmlEncode(dataString);
}
}
The keyword "this" prior to the first parameter type identifies this as an extension method, and the class it extends.
It would be used this way:
string foo = "bar";
string myOutput = foo.HtmlEncode();

How to create extension methods for Types

I am writing an extension method for parsing JSON string for any given type. I wanted to use the method on types instead of instances like many examples we already know, but I somewhat feel it is not supported by Visual Studio. Can someone enlighten me here? The following is the method:
public static T ParseJson<T>(this T t, string str) where T: Type
{
if (string.IsNullOrEmpty(str)) return null;
var serializer = new JavaScriptSerializer();
var obj = serializer.Deserialize<T>(str);
return obj;
}
I want to call the method in this fashion:
var instance = MyClass.ParseJson(text);
Thanks
The short answer is it cannot be done; extension methods need to work on an instance of something.
To use the extension method, you would have to do:
var instance = typeof(MyClass).ParseJson(text);
The token "MyClass" is not a Type instamce intself, but using typeof will get you a Type to operate on. But how is this any better than:
var instance = JsonUtility.ParseJson<MyClass>(text);
Edit: Actually, the code for the extension method still would not do what you wanted. It will always return a "Type" object, not an instance of that Type.
You can't create extension methods that apply to the type itself. They can only be called on instances of a type.
As stated in the accepted answer, you can't. However, provided that you have an extension method that can be called from an instance of T:
public static T ParseJson<T>(this T t, string s)
You could write a utility method like this:
public static T ParseJson<T>(string s)
where T: new()
=> new(T).ParseJson(s);
And call it like this:
var t = Utilities.ParseJson<T>(s);
I am afraid that's the best you can do...
You can create and extension method
public static class MyExtensions
{
public static string Serialize<T>(this T self)
{
return JsonSerializer.Serialize(self);
}
}
And use it like
instance.Serialize();
You don't have to use it like instance.Serialize<Type>(); because most of the time (if not all the time) it can be inferred from the usage.

Categories