Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a "with" method on immutables

I'd like to mimic the F# 'with' keyword (which can be used on records) in C#.

For now, when i create a new immutable class, I just add manually some custom "with" methods like this :

public class MyClass
{
    public readonly string Name;
    public readonly string Description;

    public MyClass(string name, string description)
    {
        this.Name = name;
        this.Description = description;
    }

    // Custom with methods
    public MyClass WithName(string name)
    {
        return new MyClass(name, this.Description);
    }

    public MyClass WithDescription(string description)
    {
        return new MyClass(this.Name, description);
    }
}

For my personal c# development, I tried to create a generic method to do this (in a perfect world, I would use F#). The "best" I did is something like :

    public static class MyExtensions
    {
        public static TSource With<TSource, TField>(
            this TSource obj, 
            string fieldName, 
            TField value) 
            where TSource : class
        {
            // Reflection stuff to use constructor with the new value 
            // (check parameters names and types)...
        }
    }

It works but I'm not quite satisfied because I lose compile time errors by using a string parameter (for now I don't care of performance issues).

I'd really like to be able to write something like the code below, where I replace the string parameter by a "projection" lambda :

var myClass1 = new MyClass("name", "desc");
var myClass2 = myClass1.With(obj => obj.Name, "newName");

My extension method would look something like :

    public static TSource With<TSource, TField>(
        this TSource obj, 
        Expression<Func<TSource, TField>> projection, 
        TField value)
        where TSource : class
    {
        // TODO
    }

So here are my questions :

  • Is it possible to use reflection on the projection's result and get the field name from it ?
  • Has someone else already done a robust "with" method in C# ?
like image 301
Emmanuel Horrent Avatar asked Nov 17 '14 21:11

Emmanuel Horrent


People also ask

What special methods to immutable containers use?

The from method allows for “editing” operations on immutable values by initializing the builder with attribute values taken from an existing immutable object. This could be used to prevent structural sharing as happens with copy-methods, or to accumulate collection elements from attributes of multiple values.

Can we create custom immutable class in Java?

Immutable class in java means that once an object is created, we cannot change its content. In Java, all the wrapper classes (like Integer, Boolean, Byte, Short) and String class is immutable. We can create our own immutable class as well.


1 Answers

This can certainly be done and is approach that is used in several places including Entity Framework. In EF it is used for including properties in a query.

DbContext.Categories.Include(c=>c.Products)

A query over this set will also pull the products in a category. You can examine the expression in your extension method and extract the member info like this

((System.Linq.Expressions.MemberExpression)projection.Body).Member

Of course in practice you will need some error handling to make sure the expression is a member expression. Then you can use reflection to set the appropriate property. You will need a setter for this to work but you can access private setters via reflection so the types can still be effectively immutable. This is not a perfect solution but I guess it is close enough.

I am not aware of any existing implementation of such a method. I am curious to see your full version.

like image 126
Stilgar Avatar answered Sep 20 '22 19:09

Stilgar