首页 > 解决方案 > C#按优先级获取第一个非空属性

问题描述

我目前有一个具有多个字符串属性的类。其中一个或多个可能具有值。我需要做的是根据某些优先级获得第一个非空属性。这是我设想的类的示例:

public class MyClass
{
    [Priority(1)]
    public string HighestPriority { get; set; }

    [Priority(2)]
    public string MiddlePriority { get; set; }

    [Priority(3)]
    public string LowestPriority { get; set; }
}

或者,也许使用另一个可用于确定设置的最高枚举属性?

public enum Priority
{
    HighestPriority,
    MiddlePriority,
    LowestPriority
}

public class MyClass
{
    private string highestPriority;
    public string HighestPriority 
    { 
        get; 
        set
        {
            highestPriority = value;
            HighestSetProperty = Priority.HighestPriority;
        }
    }

    private string middlePriority;
    public string MiddlePriority
    { 
        get; 
        set
        {
            middlePriority = value;
            if (HighestSetProperty != Priority.HighestPriority)
                HighestSetProperty = Priority.MiddlePriority;
        }
    }

    private string lowestPriority;
    public string LowestPriority
    { 
        get; 
        set
        {
            lowestPriority = value;
            if (HighestSetProperty != Priority.HighestPriority || HighestSetProperty != Priority.MiddlePriority)
                HighestSetProperty = Priority.LowestPriority;
        }
    }

    public Priority HighestSetProperty { get; set; }
}

那么,在switch语句中使用HighestSetProperty设置字符串呢?

到目前为止,我所知道的在不使用上述某种形式的优先级属性的情况下找到第一个非空属性的唯一方法是这样的:

string highestPriorityProp = String.IsNullOrWhitespace(HighestPriority) ? (String.IsNullOrWhitespace(MiddlePriority) ? LowestPriority : MiddlePriority) : HighestPriority;

如果添加更多属性,这显然是混乱的并且不能很好地扩展。那么,这样做的最佳方式是什么(就可读性、速度和可扩展性而言)?提前致谢。

编辑:让我们追求清洁度和可扩展性而不是速度。

编辑:重复的问题实际上并没有回答我的问题。由于属性可能不在优先级顺序中。因此,循环通过的第一个可能比最高的一组具有更低的优先级。例如:

public class MyClass
{
    public string MiddlePriority { get; set; }

    public string HighPriority { get; set; }
}

编辑:感谢大家的帮助。正如 mjwills 和我在评论中讨论的那样,接受的答案将适合我的需要,因为我的班级中只有大约 6 个属性。但是,如果有更多,重复的答案可能是最好的方法。

标签: c#

解决方案


通常你可以用coalesce操作符做这样的事情:

var highest = high ?? medium ?? low;

但是您似乎想将“null”和“empty string”视为相同。因此,编写一个将空字符串转换为空值的函数:

Func<string,string> func = s => s == "" ? null : s;

然后合并:

var highest = func(HighestPriority) ?? func(MediumPriority) ?? func(LowPriority);

我推荐这个而不是使用属性和反射。是的,当您添加新属性时,您必须修改代码,但您已经在修改代码以添加属性本身 - 仅将一半的解决方案自动化是没有意义的。虽然使用“灵活”的解决方案和反射是一种常见的诱惑,但根据我的经验,从长远来看它通常会适得其反。

如果您同意自动缩放和吸收越来越多的属性的想法,我建议使用 List 或 Dictionary 并使用First()之类的东西。


推荐阅读