如何将具有相同主体但不同签名的方法合并在一起?

时间:2014-01-21 07:47:14

标签: c# .net refactoring

这是一个重构问题。

如何将所有这些Check()方法合并到一个Generic Check()方法中,因为它们的方法体是相同的?

ppublic class ChangeDetector : IChangeDetector
{
    private readonly IEqualityHelper _equalityHelper;

    public ChangeDetector(IEqualityHelper equalityHelper)
    {
        _equalityHelper = equalityHelper;
    }

    public bool ChangeDetected { get; private set; }

    public void Check<T>(IList<T> existingList, IList<T> newList) where T : IdentifiedActiveRecordBase<T>, new ()
    {
        if (!this._equalityHelper.Equals(existingList, newList))
        {
            NotifyChange();
        }
    }

    public void CheckEntities<T>(IdentifiedActiveRecordBase<T> existingObj, IdentifiedActiveRecordBase<T> newObj) where T : IdentifiedActiveRecordBase<T>, new()
    {
        if (!this._equalityHelper.Equals(existingObj, newObj))
        {
            NotifyChange();
        }
    }

    public void Check(string existing, string newVal)
    {
        if (!this._equalityHelper.Equals(existing, newVal))
        {
            NotifyChange();
        }
    }

    public void Check<T>(T existing, T newVal) where T : struct 
    {
        if (!this._equalityHelper.Equals(existing, newVal))
        {
            NotifyChange();
        }
    }

    public void Check<T>(T? existing, T? newVal) where T : struct 
    {
        if (!this._equalityHelper.Equals(existing, newVal))
        {
            NotifyChange();
        }
    }

    private void NotifyChange()
    {
        ChangeDetected = true;
    }
}

我的EqualityHelper类成员有不同的身体,但很好:

public class EqualityHelper : IEqualityHelper
    {
        public bool Equals<T>(IList<T> existingList, IList<T> newList) where T : IdentifiedActiveRecordBase<T>, new()
        {
            if (existingList == null || existingList.Count == 0)
            {
                if (newList != null && newList.Count > 0)
                {
                    return false;
                }
            }
            else
            {
                if (newList == null
                    || existingList.Count != newList.Count
                    || newList.Any(newListItem => existingList.Any(existingListItem => existingListItem.Id == newListItem.Id)))
                {
                    return false;
                }
            }

            return true;
        }

        public bool Equals<T>(IdentifiedActiveRecordBase<T> existingObj, IdentifiedActiveRecordBase<T> newObj) where T : IdentifiedActiveRecordBase<T>, new()
        {
            if (existingObj == null)
            {
                if (newObj != null)
                {
                    return false;
                }
            }
            else
            {
                if (newObj == null || existingObj.Id != newObj.Id)
                {
                    return false;
                }
            }

            return true;
        }

        public bool Equals(string existing, string newVal)
        {
            return string.Equals(existing, newVal);
        }

        public bool Equals<T>(T existing, T newVal) where T : struct
        {
            return !existing.Equals(newVal);
        }

        public bool Equals<T>(T? existing, T? newVal) where T : struct
        {
            if ((existing.HasValue && !newVal.HasValue)
                || (!existing.HasValue && newVal.HasValue)
                || existing.Equals(newVal))
            {
                return false;
            }

            return true;
        }
    }

2 个答案:

答案 0 :(得分:1)

仅仅因为方法体看起来相似并不意味着方法签名可以合并。您的五个Handle方法中的每一个都调用五种不同的Equals - 方法,因此除非您可以合并五种Equals方法,否则无法合并Handle方法。你不能这样做,因为Equals方法的实现是不同的。请记住,要调用哪个Equals方法是由编译时决定的,而不是运行时。

修改

} }}。然后在Handle/Check - 方法中执行运行时类型检查,这会产生一个switch-case到你在类型转换的帮助下已经拥有的五个Equals方法。这将使实现更慢,并且只能更可维护。我不确定我会走那条路。

答案 1 :(得分:1)

方法体实际上并不相同,因为它们都调用了不同的Equals()方法。你打算做什么(如果我理解正确的话)完成一个Handle<T>()方法,其中T可以是任何类型。考虑一下您在代码中尝试表达的内容,如果您有一个Handle<T>()方法,则应该能够调用一个Equals<T>()方法,这似乎是公平的。这样,您可以实现一次处理逻辑(以后可能会变得更复杂,但您只需要编写一次),并且委托将对象与等式比较器类进行比较的棘手业务。