0

我得到了这个代码:

List<string> values = getValues();
Details detailsData = getDetails();

if (values[0].Equals(detailsData.Attr1))
    if (values[1].Equals(detailsData.Attr2))
        if (values[2].Equals(detailsData.Attr3))
            if (values[3].Equals(detailsData.Attr4))
                if (values[4].Equals(detailsData.Attr5))
                    return true;

getValues()返回我希望 (^^) 存在于Details对象上的字符串列表。

是否有更有效或更“漂亮”的方式来实现上面的代码?

编辑

 class Details : MainDetails
{
    string Attr3{ get; set; }
    string Attr4{ get; set; }
    string Attr5{ get; set; }
}

 class MainDetails
{
    string Attr1{ get; set; }
    string Attr2{ get; set; }
}

顺便说一句,可能还有其他一些对象,例如扩展 MainDetails 并需要此验证的 Details。所以这是代码将被多次使用。

4

6 回答 6

4

简单改进:

if (values[0].Equals(detailsData.Attr1) &&
    values[1].Equals(detailsData.Attr2) &&
    values[2].Equals(detailsData.Attr3) &&
    values[3].Equals(detailsData.Attr4) &&
    values[4].Equals(detailsData.Attr5))
{
    return true;
}

如果你只在一个地方做这件事,我不会再费心了。如果你在几个地方做同样的事情,你可能会考虑设置一个函数,例如将你Details变成另一个函数List<string>,然后使用 eg 比较它们SequenceEquals

编辑:虽然我考虑得越多,将平面字符串列表与类层次结构中的一个进行比较似乎越是一个坏主意,这是一个如何以可扩展方式执行此操作的示例。基类“消耗”前两个值,然后交给派生类检查其余值:

class MainDetails
{
    string Attr1 { get; set; }
    string Attr2 { get; set; }

    protected virtual bool Matches(IEnumerator<string> e)
    {
        // Check the first two items exist and match
        return
            e.MoveNext() && e.Current.Equals(Attr1) &&
            e.MoveNext() && e.Current.Equals(Attr2);
    }

    public bool Matches(IEnumerable<string> details)
    {
        using (var e = details.GetEnumerator())
        {
            // Check the details match. (Optionally check
            // that there are no "extra" details.)
            return Matches(e); // && !e.MoveNext();
        }
    }
}

class Details : MainDetails
{
    string Attr3 { get; set; }
    string Attr4 { get; set; }
    string Attr5 { get; set; }

    protected override bool Matches(IEnumerator<string> e)
    {
        // Check the MainDetails match, and the next three too.
        return base.Matches(e) &&
            e.MoveNext() && e.Current.Equals(Attr3) &&
            e.MoveNext() && e.Current.Equals(Attr4) &&
            e.MoveNext() && e.Current.Equals(Attr5);
    }
}

...

List<string> values = getValues();
Details detailsData = getDetails();

if (detailsData.Matches(values))
    return true;

我不确定您的确切用例,但希望这能给您一些想法。

于 2013-02-26T12:02:06.450 回答
2

如果您不能将所有属性更改为都在一个数组中,那么您至少可以将代码编写得更漂亮一些……尽管这是非常主观的!

List<string> values = getValues();
Details detailsData = getDetails();

if
(
    values[0].Equals(detailsData.Attr1) &&
    values[1].Equals(detailsData.Attr2) &&
    values[2].Equals(detailsData.Attr3) &&
    values[3].Equals(detailsData.Attr4) &&
    values[4].Equals(detailsData.Attr5)
)
{
    return true;
}
于 2013-02-26T12:02:54.660 回答
1

如果你想要一个干净的代码,你可以在你的类上放置一些索引器。

    class Details : MainDetails
    {
        string Attr3 { get; set; }
        string Attr4 { get; set; }
        string Attr5 { get; set; }

        public override string this[int index]
        {
            get
            {
                switch (index)
                {
                    case 3:
                        return Attr3;
                    case 4:
                        return Attr4;
                    case 5:
                        return Attr5;
                }
                return base[index];
            }
        }
    }

    class MainDetails
    {
        string Attr1 { get; set; }
        string Attr2 { get; set; }

        public virtual string this[int index] 
        {
            get
            {
                switch (index)
                {
                    case 1:
                        return Attr1;
                    case 2:
                        return Attr2;
                    default:
                        throw new NotImplementedException();
                }
            }
        }
    }

这样你就可以使用for循环来比较

for(int i = 0; i < 5; i++)
{
   if(values[i] != detailsdata[i+1])
      return false;
}
return true;

只需在类上放置一个方法,如 GetAtttributValue(int i);

于 2013-02-26T12:11:15.313 回答
0

当您的属性被这样命名时,没有“更清晰”的方法可以做到这一点。您可以使用反射(节省 2 行代码),但这会遇到性能问题。

于 2013-02-26T12:04:18.107 回答
0

我会说类似

List<string> values = getValues();
Details detailsData = getDetails();

if (values.SequenceEqual(new[] { detailsData.Attr1, detailsData.Attr2, detailsData.Attr3, detailsData.Attr4, detailsData.Attr5, }))
    return true;

这使用了SequenceEqualLINQ 的扩展方法,见MSDN:Enumerable.SequenceEqual<TSource>

于 2013-02-26T12:04:24.070 回答
0

除了罗林斯的回答。将详细信息对象转换为列表的函数可能如下所示:

private static IEnumerable<string> GetDetailProperties(Details details) {
    yield return details.Attr1;
    yield return details.Attr2;
    yield return details.Attr3;
    yield return details.Attr4;
    yield return details.Attr5;
}

您可以使用 SequenceEquals 方法来比较两个列表。

于 2013-02-26T12:06:35.333 回答