我有一个方法,它没有任何T参数.
遗憾的是,如下所示,C#typeof运算符不适用于泛型.
public static string ToString(object obj)
{
if (obj.GetType() == typeof(List<object>))
{
return "Bug: Never called";
}
if (obj.GetType() == typeof(List<int>))
{
return "Method only works for int lists";
}
return "";
}
Run Code Online (Sandbox Code Playgroud)
预期输出:ToString(整数列表)将返回"Bug:Never Called".
实际输出:"方法仅适用于int列表"
这在Java中运行得非常好.你会说c#中的泛型不支持这个.如何重构我的代码以使"ToString(object)"方法适用于对象列表?
要求:您不能修改方法的签名,只能修改它的实现.
不幸的是你不能让"int"类实现一个接口.因为int类是由Microsoft编写的.因此我无法在int类型上添加访问者模式.
人们已经证明无数次,这yield return比人们慢list.
然而,当我尝试一个基准测试时,我得到了相反的结果:
Results:
TestYield: Time =1.19 sec
TestList : Time =4.22 sec
Run Code Online (Sandbox Code Playgroud)
在这里,List慢了400%.无论大小如何都会发生 这毫无意义.
IEnumerable<int> CreateNumbers() //for yield
{
for (int i = 0; i < Size; i++) yield return i;
}
IEnumerable<int> CreateNumbers() //for list
{
var list = new List<int>();
for (int i = 0; i < Size; i++) list.Add(i);
return list;
}
Run Code Online (Sandbox Code Playgroud)
以下是我如何使用它们:
foreach (var value in CreateNumbers()) sum += value;
Run Code Online (Sandbox Code Playgroud)
我使用所有正确的基准规则来避免冲突的结果,所以这不是问题.
如果你看到底层代码,yield return是一个状态机憎恶,但它更快.为什么?
编辑:所有答案都复制了,确实Yield比列表更快.
New Results With …Run Code Online (Sandbox Code Playgroud) 让我们说我们有一个"ISomething"接口,方法是"DoSomething".
我们创建了多个实现它的类.示例5/10/100/1000新类定义.
将迭代List <ISomething>并且调用DoSomething()花费相同的时间,而不管添加到列表中的#unique类.假设列表包含相同数量的对象.不同类型的比较列表与相同类型的列表.
本质上我问的是接口方法调用是否始终是"常量"运行时成本,或者它取决于它背后的#唯一类型.
我为什么这么问?我需要了解界面如何在幕后工作,以免触发意外开销.
编辑:我可以提出更难的问题吗?
让我们考虑相反的情况,我们现在只有1个类,但它实现了N个接口(ISomething1 ... N).无论在它实现的#interfaces上,性能是否相同.让我们说大多数接口最终都指向同一个方法.
Edit2: adjan的答案提出了另一个潜在问题:
他说c#为每个接口生成一个v表=>所有方法都花费O(1).
让我们考虑以下场景.
垂直继承链:A0延伸A1延伸A2 ...延伸AN.
我们构造它们的所有这些类都没有变量.
我们刚刚创建了一个性能错误.
A0.method()花费O(N).
I0.method()花费O(1).
如果接口可以以恒定的开销完成工作,那么如果有人滥用继承机制并创建深度为N的垂直树分支,为什么要支付可变成本.
A0虚拟方法是否花费O(N)?它的构造函数或它的析构函数,我们100%安全地假设它需要不断的运行时成本.关于构造函数,对A0的构造函数的调用触发A1的无参数构造函数,因此调用链继续...因此O(N)成本.
C#编译器:
错误CS0738:Field<T>' does not implement interface memberField.Value.get'和最佳实现候选Field<T>.Value.get' return typeT'不匹配接口成员返回类型`object'
public interface Field
{
object Value {get;}
}
public class MyField<T> : Field
{
T _value;
public T Value
{
get
{
return _value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
为什么?List <T>在microsoft类中扩展List,但我作为用户(复制相同的设计模式)是不允许这样做的?为什么?
尝试T:对象也会产生编译错误......
我该如何解决?
关于同一主题的其他1.000.000个主题,说:
blablabla,'返回类型协方差',blablabla,'你不能'.
他们没有提出如何编译这种野兽的解决方案或解决方法.要求:
1)Field是一个不能使用泛型的接口.被称为"统一"的邪恶框架禁止泛滥.
2)"实现字段"的字段<T>具有通用T.
在C#中,以下代码片段做了什么?
1)
if (!object)
{
//code
}
Run Code Online (Sandbox Code Playgroud)
2)
if (object)
{
//code
}
Run Code Online (Sandbox Code Playgroud)
object是一个类的实例,绝对不是bool.
1)在Java中,尝试上面的代码会使编译器发出错误.只有布尔变量可以用作Condition_Block.这按预期工作.
2)在C++中,if (!object){/**/}用于空检查.
3)在C#中,编译器不发出错误并愉快地编译它.谷歌从未提及过!操作员用于对象.它只给出bool值的搜索结果.再加上侮辱伤害,它会让人们谈论的结果?和?? 运营商,这些运营对于团结开发者来说可能有30到40年的时间.仅支持NET3.5 API.如果!运算符在C++中工作,为什么人们需要?和?? ??
编辑:完整代码.
using UnityEngine;
using System.Collections;
public class Foo : MonoBehaviour
{
void Start ()
{
Foo a = new Foo();
if (a) Debug.Log("a");
if (!a) Debug.Log("b");
}
}
Run Code Online (Sandbox Code Playgroud)
它在执行时打印"b".
c# ×5
generics ×2
performance ×2
benchmarking ×1
covariance ×1
if-statement ×1
java ×1
typeof ×1
types ×1
wildcard ×1