COM 对象上的扩展方法不好吗?

Are Extension Methods on COM objects bad?

我想为 Outlook 的 Recipients 对象制作一个 .ToList() 扩展方法,但我不确定这是否是好的做法。它会创建对需要清理的对象的额外引用,还是只要我清理原始 Recipients 对象就可以了?扩展名将像这样使用。

private void Foo()
{
    Recipeints recipients = mailItem.Recipients //Original recipients
    if(recipients.ToList().Intersect(listOfRecipients).Any())
    { }
    OutlookEx.ReleaseComObject(ref recipients);
}

public static class Extensions
{
    public static List<string> ToList(this Outlook.Recipients recipients)
    {
        List<string> list= new List<string>();

        if(recipients == null)
            return null;

        for (int i = 1; i <= recipients.Count; i++)
        {
            Outlook.Recipient r = recipients[i];
            list.Add(r.Name);
            OutlookEx.ReleaseComObject(ref r);
        }

        return list
    }
}

扩展方法在成本方面与实例方法没有什么不同。实例方法有一个指向自身的隐藏参数,实例方法有相同的概念,只是它对开发者不隐藏。调用堆栈最终看起来一样,内存压力也一样。

换句话说,如果您认为使用一个函数是合理的,就没有理由(除了样式和可重用性)将其作为扩展方法。

Would it create an extra reference to the object that would need to be cleaned up or would it be fine as long I clean up the original Recipients object?

否 - 扩展方法只是可以以不同方式调用的静态方法。只要您不在某处存储 recipients 参数,它就会在方法完成后立即超出范围,并且不需要 "cleaned up"。但是如果它是一个静态的非扩展方法或者一个实例方法,那就没有什么不同了。

扩展方法只是静态方法

创建扩展方法不会导致创建额外的引用,扩展方法是静态方法的语法糖,它们仍然是静态方法,但只允许您调用它们更人性化的方式。

var ls = Extensions.ToList(recipients)
//is equivalent to 
var ls = recipients.ToList()

您仍然需要正确清理您的 COM 对象

话虽如此,您仍然需要在静态方法中正确清理和管理非托管资源,与在其他任何地方实施该方法的处理方式应该没有任何不同