0

Is something like that possible?

Let's say I have the String Class. And I want to add a Method DoStringCalc(). Now I want one Class which holds all these special strings and calls DoStringCalc() on all of them. But every String can have a different logic in DoStringCalc() and there can be thousands of them.

Most logical for me (coming from java) would be to override the Method DoStringCalc() when initializing a new String. e.g:

String hello = new String() {
    public override DoStringCalc() {
        //do something here
    }
}

How is this solved in C#?

Thypari
  • 801
  • 1
  • 6
  • 22
  • You can't extend classes like this in C#. You could do some funky stuff to hack around it, but how about just passing in an action into the class constructor? – DavidG Dec 05 '17 at 10:17
  • Action sounds about right. Could you make a small example using my example? I can then mark your post as answer. – Thypari Dec 05 '17 at 10:18

4 Answers4

3

If you have many different calculations logic, consider passing the transformation function to the class. Wrap the value which you will work with by a class and also store an appropriate tranformation in the same class:

public class Foo
{
    public string Value;
    private Func<string, string> doStringCalc;

    public Foo(string value, Func<string, string> doStringCalc)
    {
        this.Value = value;
        this.doStringCalc = doStringCalc;
    }

    public void ExecuteTransform()
    {
        this.Value = this.doStringCalc(this.Value);
    }
}

Then add different transforms as follows:

var foo1 = new Foo("A", (initialValue) => initialValue + initialValue);
var foo2 = new Foo("B", (initialValue) => initialValue + "bar");
var foo3 = new Foo("C", (initialValue) => " ");

foo1.ExecuteTransform();
foo2.ExecuteTransform();
foo3.ExecuteTransform();

Debug.WriteLine(foo1.Value); // prints "AA"
Debug.WriteLine(foo2.Value); // prints "Bbar"
Debug.WriteLine(foo3.Value); // prints " "
Michał Żołnieruk
  • 2,095
  • 12
  • 20
  • What's the difference between using Func and Action (DavidG's answer?) – Thypari Dec 05 '17 at 10:23
  • 1
    Func is returning a value, Action is not. If you want to only do something, use Action, but if you want to calculate something and store the value, Func is more appropriate – Michał Żołnieruk Dec 05 '17 at 10:25
1

If I understand correctly interface is what you are looking for.

Create an interface that requires a method DoStringCalc(). Then have all the string classes inherit the interface and implement their DoStringCalc() method. After that you can e.g. use a strongly typed List List<IExampleInterface> that allows instances of any of the string classes and call their respective DoStringCalc() from it.

NotFound
  • 5,005
  • 2
  • 13
  • 33
  • How do I make a Class that is not created by me inherit from a new interface? e.g. String, Integer, etc. – Thypari Dec 05 '17 at 10:15
  • @Thypari: _"Let's say I have the String Class. And I want to add a Method DoStringCalc()"_ How you add methods to `System.String` or `System.Int32` at all? You haven't mention that these are .NET classes – Tim Schmelter Dec 05 '17 at 10:19
  • Not quite sure how I would go about doing that. Maybe use an extension method that takes a Func as parameter? – NotFound Dec 05 '17 at 10:24
1

One option is to pass in an Action as part of the class constructor (or a Func if you want to return a value). For example:

public class MyThing
{
    private Action<MyThing> _doCalc { get; set; }

    public MyThing(Action<MyThing> doCalc)
    {
        _doCalc = doCalc;

    }

    public void DoCalc()
    {
        _doCalc(this);
    }

    public string SomeString { get; set; }
}

And call it like this:

var thing = new MyThing(t => Console.WriteLine(t.SomeString));
thing.SomeString = "Hello world";
thing.DoCalc();

Another variation of this would be to create a generic wrapper class, for example:

public class Wrapper<T>
{
    private Action<T> _doCalc { get; set; }

    public Wrapper(Action<T> doCalc)
    {
        _doCalc = doCalc;
    }

    public T Value { get; set; }

    public void DoCalc()
    {
        _doCalc(this.Value);
    }
}

And now you can do this:

var stringWrapper = new Wrapper<string>(t => Console.WriteLine("string wrapper"));
var intWrapper = new Wrapper<int>(t => Console.WriteLine("int wrapper"));

stringWrapper.DoCalc();
intWrapper.DoCalc();
DavidG
  • 113,891
  • 12
  • 217
  • 223
  • Don't forget that the class I want to extend is a .net class. Is this still possible? Could I just make the class extend String? – Thypari Dec 05 '17 at 10:22
  • You can't extend `string`, those classes are off limits for you - and they should be too. – DavidG Dec 05 '17 at 10:23
  • Updated with another variation, a generic class to wrap around any type you wish that still takes an `Action` – DavidG Dec 05 '17 at 10:30
  • Thank you! This helped me find the right solution to my problem! – Thypari Dec 05 '17 at 10:42
0

as far as I know it is not possible to change classes you do not own the sourcecode. E.g. .Net Classes.

You can extend existing classs with Extensionmethods:

public static classe StringExtension
{
    public static void DoStingCalc(this string str)
    {
         //Do your Stuff here
    }
}

If you want to Force a specific Method. You have to derive from your class an decorate it with the interface you want to ensure. Or make an abstact method declaration.