Loading

白用了C#这么多年 ! 原来静态函数还有这说法 ?

起因

为了方便比较版本号,所以想到用 struct 封装一个结构体并重载它的操作符.

因为不常使用操作符重载,以为它的成员访问级别应该和普通的静态函数没有区别

直到使用时无意间发现

它竟然能访问到对应成员的私有成员 !!!

然后继续探索

发现只要静态函数的入参中有和静态函数所属类型相同的实例,该静态函数可以直接访问对应类型的入参实例的私有成员!!!

例如:
image

从而可以做到在重载类型操作时不必要公开一些成员访问, 达到类似 C++ 友元函数 的成员访问的效果(但是不能像C++一样在其他类中定义,只能在该类中定义) 非常便捷

例如:
image

也可以访问私有函数

image

完整代码


using System.Collections.Immutable;
using System.Security.Cryptography;

VersionNumberString v = "3.1.5";

partial class NewClass
{
    private string _value;
    
    public static void VisitPrivateMember(NewClass instance)
    {
        instance._value.Dump();
    }
}

partial class NewClass
{
    public static void PartialVisitPrivateMember(NewClass instance)
    {
        VisitPrivateMember(instance);
    }
}


struct VersionNumberString
{
    private string _value;
    private char _splitCharacter;
    private Lazy<ImmutableArray<int>> _parts;
    
    private const char  DEFAULT_SPLIT_CHARACTER_A = '.';
    
    private const char  DEFAULT_SPLIT_CHARACTER_B = ',';
    
    private const char  DEFAULT_SPLIT_CHARACTER_C = '&';

    public VersionNumberString(string value, char splitCharacter)
    {
        _value = value;
        _splitCharacter = splitCharacter;
        _parts = new(InitParts);
    }
    
    public static implicit operator string(VersionNumberString v)
    {
        return v._value;
    }
    
    public static implicit operator VersionNumberString(string version)
    {
        var splitCharacter = VersionNumberString.DetectSplitCharacter(version);
        
        return new VersionNumberString (version,splitCharacter);
    }
    
    private static char DetectSplitCharacter(string source)
    {
        var span = source.AsSpan();
        
        int index = span.IndexOfAny(
            DEFAULT_SPLIT_CHARACTER_A,
            DEFAULT_SPLIT_CHARACTER_B,
            DEFAULT_SPLIT_CHARACTER_C
        );
        
        // 有下标截取一个字符,没有下班直接移动到最后
        var range = index != -1
            ? span[index..(index+1)]
            : span[span.Length..];
            
        var e = range.GetEnumerator();
        
        if(!e.MoveNext())
        {
            return ' ';
        }
        
        return e.Current;
    }
    
    ImmutableArray<int> InitParts()
    {
        if(_splitCharacter ==' ')
        {
            return int.TryParse(_value,out int parsedVerion)
             ? ImmutableArray.Create<int>(parsedVerion)
             : ImmutableArray.Create<int>();
        }
        
        var span = _value.AsSpan();

        int startIndex = default;

        List<int> result = new(span.Length-1);

        for (int i = 0; i < span.Length; i++)
        {
            if (span[i] == _splitCharacter)
            {
                var n = int.Parse(span[startIndex..i]);

                result.Add(n);

                startIndex = i + 1;
            }
            else if (i == span.LastIndexOf(_splitCharacter) + 1)
            {
                var lastChar = span.Slice(i, span.Length - startIndex);

                result.Add(int.Parse(lastChar));
            }
        }

        return result.ToImmutableArray();
    }
}

posted @ 2024-06-21 11:09  有什么不能一笑而过呢  阅读(22)  评论(0编辑  收藏  举报