Argumentlose Methoden sind in OOP böse, und hier erfahren Sie, wie Sie damit umgehen

Hallo!



Die Idee ist, faul zwischengespeicherte Eigenschaften überall in unveränderlichen Objekten zu verwenden, wo wir normalerweise prozessorlastige Methoden ohne Argumente verwenden würden. Und der Artikel - wie man es gestaltet und warum.





Visueller Zugriff auf eine Lazy-Eigenschaft eines Objekts



Haftungsausschluss

:

1) - , — ,

2) (, SRP)

3) ,



TL; DR ganz unten.



Warum böse?



. , Integer, :



public sealed record Integer(int Value);


Value int. , :



public sealed record Integer(int Value)
{
    public Integer Triple() => new Integer(Value * 3);
}


, , . ,



public int SomeMethod(Integer number)
{
    var tripled = number.Triple();
    if (tripled.Value > 5)
        return tripled.Value;
    else
        return 1;
}


,



public int SomeMethod(Integer number)
    => number.Tripled > 5 ? number.Tripled.Value : 1;


, , , . , , Tripled .



?



  1. . , , .
  2. . , , ( — ).
  3. . immutable object, , Equals GetHashCode , - , .


, , . , :



public sealed record Number(int Value)
{
    public int Number Tripled => tripled.GetValue(@this => new Number(@this.Value * 3), @this);
    private FieldCache<Number> tripled;
}


, , Cacheable. source- , - . — , .



:



1 ( ?):



public sealed record Number(int Value)
{
    public int Number Tripled => new Number(@this.Value * 3);
}


( )



2 ( Lazy<T>):



public sealed record Number : IEquatable<Number>
{
    public int Value { get; init; }  //   ,   
    public int Number Tripled => tripled.Value;
    private Lazy<Number> tripled;
    public Number(int value)
    {
        Value = value;
        tripled = new(() => value * 3);  //        ,      this-   
    }

    //   Equals,    ,    ,    Lazy<T>  
    public bool Equals(Number number) => Value == number.Value;
    //     GetHashCode
    public override int GetHashCode() => Value.GetHashCode();
}


, . , ? , .



, with, , (-). Lazy, .



3 ( ConditionalWeakTable):



public sealed record Number
{
    public Number Tripled => tripled.GetValue(this, @this => new Integer(@this.Value * 3));
    private static ConditionalWeakTable<Number, Number> tripled = new();
}


. ValueType ConditionalWeakTable -. , - ( , , 6 , , ).



4 ( ):



public sealed record Number
{
    public int Value { get; init; }

    public Number Tripled { get; }
    public Number(int value)
    {
        Value = value;
        Tripled = new Number { Value = value * 3 };
    }
}


stackoverflow, , "" — , .





  1. , , . ?
  2. Equals GetHashCode true 0 . , , . , Equals GetHashCode , .
  3. . , , .
  4. , GetValue, , ConditionalWeakTable. -, Lazy<T>.
  5. with, initialized holder, — .


!



, :



public struct FieldCache<T> : IEquatable<FieldCache<T>>
{
    private T value;
    private object holder; //       ,    generic 
    //    , ,   Equals     
    public bool Equals(FieldCache<T> _) => true;
    public override int GetHashCode() => 0;
}


GetValue :



public struct FieldCache<T> : IEquatable<FieldCache<T>>
{
        public T GetValue<TThis>(Func<TThis, T> factory, TThis @this) where TThis : class // record -   .   ,    
        {
            //        (,   - null)
            if (!ReferenceEquals(@this, holder))
                lock (@this)
                {
                    if (!ReferenceEquals(@this, holder))
                    {
                        //    ,    FieldCache   ,  -         . , ,     ,      
                        value = factory(@this);
                        holder = @this;
                    }
                }
            return value;
        }
}


, :



public sealed record Number(int Value)
{
    public int Number Tripled => tripled.GetValue(@this => new Number(@this.Value * 3), @this);
    private FieldCache<Number> tripled;
}


, .





, , FieldCacheLazy<T>.



Method Mean
BenchFunction 4,599.1638 ns
Lazy 0.6717 ns
FieldCache 3.6674 ns
ConditionalWeakTable 25.0521 ns


BenchFunction — - , , . . , FieldCache<T> , Lazy<T>.



, , , .



TL;DR



: , .



Und die bekannten existierenden Ansätze erlauben es anscheinend nicht, dass es schön gemacht wird, also müssen Sie Ihre eigenen schreiben.




All Articles