【问题标题】:Is there a shorthand for properties where I implement a custom method?是否有我实现自定义方法的属性的简写?
【发布时间】:2020-12-11 07:34:34
【问题描述】:
public class ServerState
{
    public static Action stateChanged;
    private string currentMap;

    public string CurrentMap
    {
        get { return currentMap; }
        set
        {
            currentMap = value;
            stateChanged?.Invoke();
        }
    }
}

我有一个包含几十个变量的类,每个变量都需要自己的属性,以便我可以调用一个动作。也就是说,我要把上面的代码重复几十次,感觉应该有更好的办法。

上面的代码有简写吗?

【问题讨论】:

  • 简短的回答是否定的。如果你使用它,你可以考虑为 Visual Studio 或 Rider 创建一个代码 sn-p
  • 你真的需要它们作为属性吗?否则,您可以将它们存储在私有 Dictionary 中并使用 T GetVariable<T>(string nameOfVariable) 之类的方法和类似的设置器。

标签: c# class-variables shorthand


【解决方案1】:

这里有几个想法:

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace ConsoleApp1
{
    public class ServerState
    {
        public static Action stateChanged;

        private Dictionary<string, object> _values = new Dictionary<string, object>();
        private void Set(object value, [CallerMemberName] string propertyName = null)
        {
            _values[propertyName] = value;
            stateChanged?.Invoke();
        }

        private T Get<T>([CallerMemberName] string propertyName = null)
        {
            if (_values.TryGetValue(propertyName, out var v)) return (T)v;
            throw new KeyNotFoundException(propertyName);
        }

        public string CurrentMap 
        { 
            get => Get<string>(); 
            set => Set(value); 
        }

        // You can make them in one line if you want
        public string CurrentMap2 { get => Get<string>(); set => Set(value); }
    }

    public class ServerState2
    {
        public static Action stateChanged;
        private string currentMap;

        private void Set<T>(ref T property, T value)
        {
            property = value;
            stateChanged?.Invoke();
        }

        public string CurrentMap
        {
            get => currentMap;
            set => Set(ref currentMap, value);
        }
    }
}

如果你想使用多个事件,或者跟踪值是否实际改变,你可以扩展这个想法:

public class ServerState
{
    public static Action currentMapChanged;
    public static Action currentMap2Changed;
    private Dictionary<string, object> _values = new Dictionary<string, object>();
    private void Set(object value, Action onChange, [CallerMemberName] string propertyName = null)
    {
        var previousValue = _values[propertyName];
        // Check if value has changed
        if (value != previousValue)
        {
            _values[propertyName] = value;
            onChange?.Invoke();
        }
    }

    private T Get<T>([CallerMemberName] string propertyName = null)
    {
        if (_values.TryGetValue(propertyName, out var v)) return (T)v;
        throw new KeyNotFoundException(propertyName);
    }

    public string CurrentMap 
    { 
        get => Get<string>(); 
        // Call `currentMapChanged` if value differs
        set => Set(value, currentMapChanged); 
    }

    // You can make them in one line if you want
    // Call `currentMap2Changed` if value differs
    public string CurrentMap2 { get => Get<string>(); set => Set(value, currentMap2Changed); }
}

此外,您应该考虑使用event 关键字来阻止其他类触发此事件。还要注意静态事件,它们在静态上下文中持有对侦听委托的引用,并且需要注意避免内存泄漏。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多