返回接口时是否有性能损失?
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 的界面类型。让我们看三个简单的例子:
- Return class 对象作为接口:最有可能的影响可以忽略不计(如图所示here)
public ILoggedData GetLoggedData() => new LoggedDataClass();
- Return struct 对象作为接口:发生装箱,一个常见的性能瓶颈 (MSDN)。
public ILoggedData GetLoggedData() => new LoggedDataStruct();
- 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 这方面的内容。
考虑一个接口和一个方法,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 的界面类型。让我们看三个简单的例子:
- Return class 对象作为接口:最有可能的影响可以忽略不计(如图所示here)
public ILoggedData GetLoggedData() => new LoggedDataClass();
- Return struct 对象作为接口:发生装箱,一个常见的性能瓶颈 (MSDN)。
public ILoggedData GetLoggedData() => new LoggedDataStruct();
- 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 这方面的内容。