Search Unity

Extend Static Class Functionality

Discussion in 'Scripting' started by Helical, Jun 17, 2019.

  1. Helical

    Helical

    Joined:
    Mar 2, 2014
    Posts:
    50
    If you search (at the time of this writing) in google

    "c# extending static class" - You will find that there is no way to do it.

    I wish to observe a technique that proximate achieves static extensions, and to discuss the potentials use cases in Unity development.

    Suppose you make a new Class

    Code (CSharp):
    1. public class MyGameName {}
    If you would wish to extend it, c# currently only allows to extend instance functions (functions that are not static)

    However if we use the Singleton pattern to enforce a single instance for this class that would be globally available

    Code (CSharp):
    1. public static MyGameName Instance {get; private set;} = new MyGameName();
    2. private MyGameName(){}
    Then all of a sudden, extending the normal way works much like the extension of the static scope of the class (which is not supported by c#)

    Code (CSharp):
    1. public Camera GetMainCamera(this MyGameName instance){
    2.     return _cachedCamera;
    3. }
    Now from anywhere in the code, writing the following retrieves the MainCamera

    Code (CSharp):
    1. MyGameName.Instance.GetMainCamera();
    Whats nice in extending over traditional modification is that each extension method could be in a separate script.

    Thats it for the design pattern implementation and usage. Basically we combine extension methods and the singleton pattern to achieve static extensioning capabilities.

    I find this techinque useful for plug and play type modules that need to add functionality to existing API. Each Service/System adds a factory

    Getting services looks like this
    upload_2019-6-17_14-39-8.png upload_2019-6-17_14-39-8.png

    What are your thoughts?
     
    ClaudiaTheDev likes this.
  2. ClaudiaTheDev

    ClaudiaTheDev

    Joined:
    Jan 28, 2018
    Posts:
    331
    You wrote:
    I find this techinque useful for plug and play type modules that need to add functionality to existing API

    But you can use it only for your own classes or classes wich already have instances which most Unity classed do not have. So for me i do not see a huge benefit.
    There are other design ways to "extent" static functionality Like inheritance on instances, just static methods in helper classes etc.
    I still like the design because it can make the code better readable than the other ways.
     
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    But it's a static class...

    All an extension method for a static class would do would be to allow you to fake a static class's name.

    Say you had 2 static classes:

    Code (csharp):
    1.  
    2.     public static class Utils
    3.     {
    4.  
    5.         public static void Foo()
    6.         {
    7.             Console.WriteLine("Foo");
    8.         }
    9.  
    10.     }
    11.  
    12.     public static class Utils2
    13.     {
    14.  
    15.         public static void Bar() extends Utils //faking an extension method of Utils
    16.         {
    17.             Console.WriteLine("Bar");
    18.         }
    19.  
    20.     }
    21.  
    If we made it so that Utils2 was making extension methods of Utils is that now instead of saying:
    Code (csharp):
    1.  
    2. Utils.Foo();
    3. Utils2.Bar();
    4.  
    You can instead say:
    Code (csharp):
    1.  
    2. Utils.Foo();
    3. Utils.Bar();
    4.  
    But so what?

    There's no new syntactical clarity.

    They're static methods in an of themselves... the syntax is the same with a mere name change. Heck you can use the 'using' statement to change the used name of a static class if you want:
    Code (csharp):
    1.  
    2. using MyCustomUtilsName = NamespaceToUtils.Utils;
    3.  
    4. //in that code file somwhere
    5. MyCustomUtilsName.Foo();
    6.  
    Of course you can't have 2 classes named the same thing via the 'using' statement though.

    ...

    This heavily differs from extension methods. An extension method allows an object (which a static class is not an object) to gain new methods that are syntactically called as if they were member methods.

    Code (csharp):
    1.  
    2. public static class ExtensionMethods
    3. {
    4.     public static void Foo(this GameObject go)
    5.     {
    6.         Debug.Log(go.name);
    7.     }
    8. }
    9.  
    10. //elsewhere
    11. ExtensionMethods.Foo(this.gameObject);
    12. //vs the syntactically more concise
    13. this.gameObject.Foo();
    14.  
    There's a clear syntactical difference going on.

    The implication is this... a member method usually mutates/modifies the state of an object, return information about the state of the object, or perform some action based on the state of the object (the common theme here being state). An extension method is intended to mimic this behaviour by taking in an object that it'll likely mutate. Therefore behaving as if it were a member method. And so the syntax sugar of extension methods allow you to convey that behaviour syntactically.

    Static classes on the other hand contain static methods.

    Static methods traditionally are stateless. If you have stateful static methods... you're probably doing static wrong and are doing the very thing that makes programmers the world over say "this is why statics/globals are BAD". It's not that statics are actually bad, it's the idea of global states that are bad. So as to avoid global states, you should follow the rule of not creating static classes/methods that maintain a state (there are of course exceptions to this rule... but I won't get into that right now).

    ...

    Anyways, tldr;, extension methods for static classes is kind of useless in my book.

    And as Gor-sky pointed out... your singleton solution (which as a design pattern is about giving object identity... state... to a global, thusly making the extension method a duh) only works for singletons you created since the Unity API as well as the .Net API doesn't particularly have many if any singletons at all. Meaning you probably have access to the source control of that class... so why do you need another class to add methods to it?

    Is it so you can break your code across multiple *.cs files? You may want to look into partial classes then:
    https://docs.microsoft.com/en-us/do...asses-and-structs/partial-classes-and-methods

    But I'm beginning to get the sneaking suspicion you're giving a single class way to much stuff to do... breaking the single responsibility principle.
     
    Last edited: Jun 17, 2019
    ClaudiaTheDev likes this.
  4. studentutu

    studentutu

    Joined:
    Oct 22, 2017
    Posts:
    121
    just for lols - you can actually make a standard extension and then use null to cast into a static class. Behold :
    public static ExtendingAssetDatabase
    {
    public static List<T> FindAllAssetsOfType where T : UnityEngine.Objetc (this AssetDatabase nullObject)
    { // implement here }
    }
    use with
    var listOfObjects = (null as AssetDatabase).FindAllAssetsOfType<T>();
     
    trombonaut likes this.