返回接口时是否有性能损失?

Is there a performance penalty when returning an Interface?

考虑一个接口和一个方法,returns一个对象实现了这个接口:

interface ILoggedData
{
    public int Id {get;}
    public string Description {get;}
}

class LoggedDataReader
{
    public ILoggedData GetLoggedData()
    {
        ...
        LoggedData loggedData = new LoggedData(...);
        return loggedData;
    }

    private class LoggedData : ILoggedData
    {
        ...
        public int Id {get; set;}
        public string Description {get; set;}
    }
}

所以LoggedDataReader.GetLoggedData创建了私有对象classLoggedData和returns接口ILoggedData.

我假设从 LoggedData 到接口的转换没有做任何事情。您可以将其视为对编译器的限制:“您只能使用这些 getter 属性”。我假设只返回对 loggedData 对象的引用,并解释为对接口的引用。

这是否正确,或者从对象到接口的类型转换实际上有什么作用吗?

I assumed that the conversion from LoggedData to the interface doesn't do anything. You can regard it as a limitation for the compile

嗯,问题就在那里。如果你认为使用接口是无用的,只会影响性能,那么为什么接口一开始就存在?

接口的使用与否与性能关系不大,与实现解耦多态性有关。

在 99.999999999999% 的情况下,决定使用接口还是具体 class 永远不应基于性能原因。

这在很大程度上取决于您 return 的界面类型。让我们看三个简单的例子:

  1. Return class 对象作为接口:最有可能的影响可以忽略不计(如图所示here)
public ILoggedData GetLoggedData() => new LoggedDataClass();
  1. Return struct 对象作为接口:发生装箱,一个常见的性能瓶颈 (MSDN)。
public ILoggedData GetLoggedData() => new LoggedDataStruct();
  1. Return 对象列表 作为接口:内存压力增加,热路径上的性能会受到很大影响。详细解释here.
public IEnumerable<ILoggedData> GetLoggedData()
{
    return new List<ILoggedData>() { new LoggedDataClass() };
}

答案...

...是!在某些情况下,“类型转换”意味着不需要的 side-effects。另一个答案没有考虑 C# 编译器的内部工作原理。例如。这是不正确:

The use or not of interfaces has very little to do with performance and all about implementation decoupling an polymorphism.

接口的使用使编译器更难,有时甚至不可能优化某些操作。最常见的陷阱是 foreach 关键字使用的 GetEnumerator 模式。具有强类型 - 例如List<T> - 编译器可以使用优化的枚举器,而对于弱类型则不然 - 例如IList<T>IEnumerable<T>.

每个 C# 开发人员都应该阅读 Lippert's blog post 这方面的内容。