C# 返回接口时是否存在性能损失?
考虑返回实现此接口的对象的接口和方法:C# 返回接口时是否存在性能损失?,c#,performance,interface,C#,Performance,Interface,考虑返回实现此接口的对象的接口和方法: interface ILoggedData { public int Id {get;} public string Description {get;} } class LoggedDataReader { public ILoggedData GetLoggedData() { ... LoggedData loggedData = new LoggedData(...);
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
创建私有类LoggedData
的对象,并返回接口ILoggedData
我假设从LoggedData到接口的转换没有任何作用。您可以将其视为编译器的一个限制:“您只能使用这些getter属性”。我假设只返回对loggedData对象的引用,并将其解释为对接口的引用
这是正确的,还是从对象到接口的类型转换实际上起了什么作用
我假设从LoggedData到接口的转换没有任何作用。您可以将其视为编译的限制
问题就在这里。如果您认为使用接口是无用的,只会影响性能,那么为什么一开始就存在接口呢
接口的使用与否与性能关系不大,而与多态性的实现无关
在99.99999999999%的情况下,使用接口或具体类的决定不应基于性能原因。这在很大程度上取决于您返回的接口类型。让我们看三个简单的例子:
public IEnumerable GetLoggedData()
{
返回新列表(){new LoggedDataClass()};
}
答案是。。。
…是是!在某些情况下,“类型转换”意味着不必要的副作用。另一个答案没有考虑C#编译器的内部工作。例如,这是不正确的:
接口的使用与否与性能关系不大
所有关于多态性的实现
接口的使用使得编译器更难,有时甚至不可能优化某些操作。最常见的陷阱是foreach
关键字使用的GetEnumerator
模式。对于强类型(例如列表
),编译器可以使用优化的枚举数,而对于弱类型(例如IList
或IEnumerable
),情况并非如此
每个C#开发人员都应该了解这一点。在这种情况下,它什么也不做。您甚至可以在类之外的任何地方调用此代码,而不会出现任何错误:var description=new LoggedDataReader().GetLoggedData().description;对于值类型,它将导致装箱,否则不会产生影响。Related:也没有,开销在方法的调用程序中,访问接口成员。每个成员大约一纳秒,这是高度优化的。你有两匹马,你想知道哪匹马跑得更快。和他们赛跑!你已经用两种方式编写了代码,所以现在用两种方式运行它,运行得更快的就是运行得更快的。OP没有说使用接口是无用的——当他们说“编译的限制”时他们正在讨论通过使用一个忽略设置器的接口来限制对属性设置器的访问。这个答案99.99999999999%不准确。接口通常会带来巨大的损失。谢谢你的链接。这个答案对于原始海报中描述的常见情况是正确的,但第一点中的“无影响”取决于许多事情是否正常。NET中存在接口使用的“坏路径”,这会导致较小但可测量的性能损失;2010年,我们在为Roslyn设计基本数据结构时,在考虑OP的问题时测量了这些影响。不幸的是,我不是测量这些影响的人,因此我不熟悉细节,而且,在这十年中,CLR可能已经进行了优化。我对原始海报的建议将是我对所有性能问题的建议。进行经验测量。关于第一点,我想没有人会注意到:P。更新了一个更准确的陈述。
public ILoggedData GetLoggedData() => new LoggedDataClass();
public ILoggedData GetLoggedData() => new LoggedDataStruct();
public IEnumerable<ILoggedData> GetLoggedData()
{
return new List<ILoggedData>() { new LoggedDataClass() };
}