How Do Extension Methods Work

How do extension methods work?

First, here's a very quick tutorial on extensions for those learning c#/Unity for anyone googling here:

Make a new text file HandyExtensions.cs like this ... (note that somewhat confusingly, you can use any name at all for the class which "holds" your extensions - the actual name of the class is never used at all, and is irrelevant) ...

 using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public static class HandyExtensions
{
public static float Jiggled(this float ff)
{
return ff * Random.Range(0.9f,1.1f);
}
}

You have now made a new "command" Jiggle(). You can use jiggle on any float. See where it says "this float ff". Because it says "float" just there, this extension works on floats.

As you can see, the Jiggled() extension will take a float and change it slightly. Try it like this

 float x = 3.5f;
Debug.Log("x is " + x);
Debug.Log("x is " + x.Jiggled() );
Debug.Log("x is " + x.Jiggled() );
Debug.Log("x is " + x.Jiggled() );
Debug.Log("x is " + x.Jiggled() );
Debug.Log("x is " + x.Jiggled() );

Do some tests like that until you have a good understanding of extensions. Learn as much as you can about extensions! Here's another tutorial.

And now the question on this page! ...


As Mikael explains, what you are looking for is not actually an extension. (Also note, if you're trying to add a field to Vector3, you cannot do that in c#.)

Now, if you want to return "that thing" you need to include the static class name up front, and you DO NOT make it an extension. It's just a normal call to a static.

wrong...

public static Vector3 MaxValue(this Vector3 _vec3)
{
return new Vector3(float.MaxValue,float.MaxValue,float.MaxValue);
}

correct...

public static Vector3 MaxValue()
{
return new Vector3(float.MaxValue,float.MaxValue,float.MaxValue);
}

you can then do this ...

Debug.Log(   ExtensionMethods.MaxValue()  );

I think that may be what you're looking for there.

You'd normally call ExtensionMethods something short like Handy so you can write

 Handy.MaxValue();

indeed, since you can't put the "Vector3 up front", something like this would be more clear:

  Handy.MaxVector3();

makes sense?

If you're trying to write something like this: Vector3.MaxValue() you can't do that ... because the "Vector3" part IS A CLASS (or Struct), not a variable. For example, this is an extension on an integer:

 375.Jiggle();

and this is an extension on an integer:

 int x;
x.Jiggle();

but this is meaningless:

 int.Jiggle();  // meaningless

To repeat for clarity, note that you asked:

I want to make an extension method in Unity3d for the Vector3 class [actually a struct]

extensions can only be called on actual variables, not on "the class or struct".

   Vector3 hero;
Vector3 enemy;
hero.Jiggle(); // works great
enemy.Jiggle(); // works great

Vector3.Jiggle(); // syntax error - meaningless

Note too that as Mikael actually mentions in his answer, you can in fact actually do this:

  (new Vector3()).Jiggle();

If you think about it that makes sense, too. One of my favorite things in c# is that you can use extensions on plain old constants:

 14.Jiggle();
7.5f.Radians();

You've got to love that unless you just get no pleasure from life. Here's an example of that:

public static Color Colored( this float alpha, int r, int g, int b )
{
return new Color(
(float)r / 255f,
(float)g / 255f,
(float)b / 255f,
alpha );
}

You can then write .. Color c = .5f.Colored(.2f,.4f,.2f); and that is a pucey color with an alpha of .5f.

I've always thought it would be great if the syntax you ask about was available, if you could have a "type" or "class" somehow as the "thing" you extend on - but it's not the case. For what you are trying to do, you have to just use a handy word such as, well, Handy, and do this

Vector3 big = Handy.MaxVec3();

I hope this explains the situation!


Again for anyone needing a general intro to extensions, intro. Here are some of my favorite extensions.

Something like the following is used in every game project...

public static float Jiggle(this float ff)
{
return ff * UnityEngine.Random.Range(0.9f,1.1f);
}

public static float PositiveOrNegative(this float ff)
{
int r = UnityEngine.Random.Range(0,2);
if (r==0) return ff;
return -ff;
}

public static bool Sometimes(this int n)
{
if (n<=1) return true;
int r = UnityEngine.Random.Range(0,n);
return (r==0);
}

Example uses..

 if ( 10.Sometimes() )
{
explode spaceship
}

it only does it once in ten times.

 if ( 3.Sometimes() )
{
laser sparkle
}

in that example it only does it about a third of the time.

(Note that indeed typically you make extensions use generics where possible. Not shown here for simplicity.)

Here's a handy extension trick. Here's a really advanced extension.

Extensions are ubiquitous in Unity engineering.

If you are one of the many folks learning to code using Unity...pretty much the first thing you should master is extensions. Try to do almost everything with an extension. Sometimes when working with Unity, almost every line of code needs one or more extensions. Enjoy!

How do extension methods work under-the-hood?

How do extension methods work under-the-hood?

They're just static methods; the compiler rewrites calls like myObject.MyExtensionMethod() to MyExtensionClass.MyExtensionMethod(myObject).

Is it better to use inheretance or extension methods on WELL-KNOWN classes that you OWN?

There's not single answer to this question, it all depends on the context. But usually extension methods are most useful in those cases:

  • you don't own the code for the extended type
  • the method targets an interface and will be the same for all implementations of this interface (e.g. IEnumerable<T> and Linq extension methods)

How extension methods are implemented internally

As already have said by other colleagues it is just a static method.
It is all about the compiler we can say that CLR even have no idea about extension methods.
You can try to check IL code ..

Here is an example

static class ExtendedString
{
public static String TestMethod(this String str, String someParam)
{
return someParam;
}
}

static void Main(string[] args)
{
String str = String.Empty;
Console.WriteLine(str.TestMethod("Hello World!!"));
........
}

And here is the IL code.

  IL_0001:  ldsfld     string [mscorlib]System.String::Empty
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldstr "Hello World!!"
IL_000d: call string StringPooling.ExtendedString::TestMethod(string,
string)
IL_0012: call void [mscorlib]System.Console::WriteLine(string)
IL_0017: nop

As you can see it is just a call of static method.
The method is not added to the class, but compiler makes it look like that.
And on reflection layer the only difference you can see is that CompilerServices.ExtensionAttribute is added.

What are Extension Methods?

Extension methods allow developers to add new methods to the public
contract of an existing CLR type,
without having to sub-class it or
recompile the original type.

Extension Methods help blend the
flexibility of "duck typing" support
popular within dynamic languages today
with the performance and compile-time
validation of strongly-typed
languages.

Reference: http://weblogs.asp.net/scottgu/archive/2007/03/13/new-orcas-language-feature-extension-methods.aspx

Here is a sample of an Extension Method (notice the this keyword infront of the first parameter):

public static bool IsValidEmailAddress(this string s)
{
Regex regex = new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$");
return regex.IsMatch(s);
}

Now, the above method can be called directly from any string, like such:

bool isValid = "so@mmas.com".IsValidEmailAddress();

The added methods will then also appear in IntelliSense:

alt text
(source: scottgu.com)

As regards a practical use for Extension Methods, you might add new methods to a class without deriving a new class.

Take a look at the following example:

public class Extended {
public int Sum() {
return 7+3+2;
}
}

public static class Extending {
public static float Average(this Extended extnd) {
return extnd.Sum() / 3;
}
}

As you see, the class Extending is adding a method named average to class Extended. To get the average, you call average method, as it belongs to extended class:

Extended ex = new Extended();

Console.WriteLine(ex.average());

Reference: http://aspguy.wordpress.com/2008/07/03/a-practical-use-of-serialization-and-extension-methods-in-c-30/

Why we use this in Extension Methods?

Because that's the way you tell the compiler that it's an extension method in the first place. Otherwise it's just a normal static method. I guess they chose this so they didn't have to come up with a new keyword and potentially break old code.

When is it correct to create an extension method?

Brad Adams has written about extension method design guidelines:

CONSIDER using extension methods in any of the following scenarios:

  • To provide helper functionality relevant to every implementation of an interface, if said functionality can be written in terms of the core interface. This is because concrete implementations cannot otherwise be assigned to interfaces. For example, the LINQ to Objects operators are implemented as extension methods for all IEnumerable types. Thus, any IEnumerable<> implementation is automatically LINQ-enabled.

  • When an instance method would introduce a dependency on some type, but such a dependency would break dependency management rules. For example, a dependency from String to System.Uri is probably not desirable, and so String.ToUri() instance method returning System.Uri would be the wrong design from a dependency management perspective. A static extension method Uri.ToUri(this string str) returning System.Uri would be a much better design.

What is Extension method and Why do we need to use it?

What is an extension method ?

Refer to this question - What are Extension Methods?

Why do we need to use it ?

Somehow, I don't agree to the idea of using extension methods to extend an existing type since practically this is impossible. The only reason why you want to use extension method is to bring fluency and readabilty on any type.

Check this code..

string str = "Hello world";
string result = Helper.Method2(Helper.Method1(str));

This code with extension methods can be written as below.

string str = "Hello world";
string result = str.Method1().Method2();
//compiler ultimately compiles this code as Helper.Method2(Helper.Method1(str));

which one is more fluent and readable ? The one with the extension methods.



Related Topics



Leave a reply



Submit