小编Mic*_*l B的帖子

垃圾收集器如何在这里避免无限循环?

考虑下面的C#程序,我在codegolf上提交它作为创建循环而没有循环的答案:

class P{
    static int x=0;
    ~P(){
        System.Console.WriteLine(++x);
        new P();
    }
    static void Main(){
        new P();
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的检查中,这个程序看起来像一个无限循环,但似乎运行了几千次迭代,然后程序成功终止而没有错误(没有抛出错误).P最终的终结者不会被称为规范违规吗?

显然这是一个愚蠢的代码,应该永远不会出现,但我很好奇该程序如何完成.

原始代码高尔夫邮件:: https://codegolf.stackexchange.com/questions/33196/loop-without-looping/33218#33218

c# garbage-collection

101
推荐指数
3
解决办法
4604
查看次数

为什么阵列协方差被认为是如此可怕?

在.NET中,引用类型数组是共变体.这被认为是一个错误.但是,我不明白为什么这么糟糕考虑以下代码:

string[] strings = new []{"Hey there"};
object[] objects = strings;
objects[0] = new object();
Run Code Online (Sandbox Code Playgroud)

哦,这个编译并在运行时失败.当我们试图将一个对象粘贴到一个字符串[]中时.好的,我同意臭,但是T []扩展了Array并且还实现了IList(并且IList<T>,我想知道它是否实现了IList<BaseType> ......>.Array和IList都允许我们犯同样的可怕错误.

string[] strings = new []{"Hey there"};
Array objects = strings;
objects.SetValue(new object(),new[]{0});
Run Code Online (Sandbox Code Playgroud)

IList版本

string[] strings = new []{"Hey there"};
IList objects = strings;
objects[0] = new object();
Run Code Online (Sandbox Code Playgroud)

T []类由CLR生成,并且必须包含对set_Item方法等效的类型检查(数组实际上没有一个).

是否担心设置为T []必须在运行时进行类型检查(这违反了编译时期望的类型安全性)?当有相同的方法通过上面提供的手段射击自己的脚时,为什么它被认为有害于阵列显示这种属性?

c# arrays

14
推荐指数
2
解决办法
2211
查看次数

F#内联如何工作?

使用F#,我理解您可以使用inline关键字在呼叫站点执行类型特化.那是::

val inline (+) : ^a -> ^b -> ^c
      when (^a or ^b) : (static member (+) : ^a * ^b -> ^c)
Run Code Online (Sandbox Code Playgroud)

约束,^a或者^b必须有一个静态成员op_Addition,或者一个内置的原语,可以用来填补空白.

因此,如果你有一个方法有一个+,你传入一个int和一个short作为参数,它解包+指令使用内置的原语为int,如果你传入一个浮点数和一个字节,它使用浮点数原始加法操作码.

这在编译时是如何完成的?你怎么能在CLR中有一个方法根据类型切换它使用的操作码或方法?

Reflection.Emit可以实现这种行为吗?我理解内联是在调用站点执行的,这是否意味着代码不能与C#一起使用?

c# f# inline

14
推荐指数
1
解决办法
1622
查看次数

在C#中使用元组更容易的任何提示?

通常你想发送多个值,但由于使用率低(即它只在一两个地方使用),很难证明创建一个新类型的合理性.

Tuple<...>KeyValuePair<,>类型是非常有用的,但不是他们真正的语言支持.

好吧,一种用于元组列表的好方法是创建一个扩展List并添加自定义add方法的类型:例如

public class TupleList<T1,T2> : List<Tuple<T1,T2>>{
    public void Add(T1 key, T2 value){
        base.Add(Tuple.Create(key, value));
    }
}
Run Code Online (Sandbox Code Playgroud)

这意味着如果我有一个方法IEnumerable<Tuple<int,string>>,我可以使用以下代码快速建立列表,如下::

Foo(new TupleList<int,string>{{1,"one"},{2,"two"},{3,"three"}});
Run Code Online (Sandbox Code Playgroud)

这使得将值变为元组列表变得更容易,因为我们不必经常说Tuple.Create,并且几乎使我们获得了很好的函数式语言语法.

但是当使用元组时,将它展开到不同的组件中是很有用的.这方面的扩展方法可能有用::

    public static void Unwind<T1,T2>(this Tuple<T1,T2> tuple,out T1 var1,out T2 var2)
    {
        var1 = tuple.Item1;
        var2 = tuple.Item2;
    }
Run Code Online (Sandbox Code Playgroud)

但即便如此,因为输出参数根本不是变体.也就是说,如果T1是一个字符串,即使它们是可分配的,我也不能发送一个对象变量,否则就像我可以用手展开一样.我无法提出你可能想要这种差异的原因,但如果它存在,我无法理解为什么你会想要失去它.

任何人都有其他技巧来制作工作元组,或者在C#中更容易像元组一样的元组?

元组的一个重要潜在用途可能是通用的memoization.这在F#这样的语言中很容易,但在C#中却很难.

我目前正在使用Tuples提供一个MethodBase和一个标记数组(常量,对象或参数标记),提供给动态构建的对象以构造某些成员字段.

由于我想在API使用者身上简化语法,因此我创建了可以使用a ConstructorInfo或a MethodInfo和params对象数组的Add方法.

编辑:Eric Lippert像往常一样有很好的动机在这里使用元组,他甚至说我怀疑那里真的没有支持: 元组设计要解决的要求是什么?

.net c# tuples

10
推荐指数
2
解决办法
2051
查看次数

无论如何用Handsontable过滤行?

我目前正在尝试在handsontable的列上添加搜索过滤器.我可以使用callback搜索插件来隐藏带有css的行但是会中断滚动.搜索插件似乎也只查看表的前100个左右.是否存在可以将行过滤添加到handsontable的插件?

handsontable

10
推荐指数
2
解决办法
1万
查看次数

如何从DynamicMethod获取IL bytearray?

作为一个新奇的东西,我试图看看IL与运行时生成的轻量级代码与VS编译器生成的代码有什么不同,因为我注意到VS代码往往会运行不同的性能配置文件管型.

所以我写了下面的代码::

Func<object,string> vs = x=>(string)x;
Expression<Func<object,string>> exp = x=>(string)x;
var compiled = exp.Compile(); 
Array.ForEach(vs.Method.GetMethodBody().GetILAsByteArray(),Console.WriteLine);
Array.ForEach(compiled.Method.GetMethodBody().GetILAsByteArray(),Console.WriteLine);
Run Code Online (Sandbox Code Playgroud)

不幸的是,这会引发异常,因为GetMethodBody显然是对表达式树生成的代码的非法操作.我怎样才能以库的方式(即不使用外部工具,除非工具有API)查看代码使用轻量级codegen生成的代码?

编辑:错误发生在第5行,编译.Method.GetMethodBody()抛出异常.

Edit2:有谁知道如何恢复方法中声明的局部变量?或者没有办法GetVariables?

c# dynamicmethod

9
推荐指数
1
解决办法
2658
查看次数

为什么TypeBuilder生成的泛型methodinfo不是泛型方法?

我有一些代码使用MethodInfo在生成的类型上找到的泛型方法.为了避免一些反思,我让代码使用了

ldtoken Method
ldtoken Type
call GetMethodFromHandle(RuntimeMethodHandle,RunTimeTypeHandle)
Run Code Online (Sandbox Code Playgroud)

用于在编译时生成MethodInfos的模式.

但是,如果methodInfo属于泛型类型,并且本身是泛型方法,那么事情就变得棘手了.这里有一些代码只是生成一个GM,它发出了一个开放版本的methodInfo.如果我调用它来检索方法而不是尝试在特定类型上关闭它,我会得到一个令人困惑的异常::

System.Reflection.MethodInfo GM[M]()不是GenericMethodDefinition.MakeGenericMethod只能在MethodBase.IsGenericMethodDefinition为true的方法上调用.

这是相关代码::

var aBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Test"), AssemblyBuilderAccess.RunAndSave);
var mBuilder = aBuilder.DefineDynamicModule(aBuilder.GetName().Name, true);
var typeBuilder = mBuilder.DefineType("NameSpace.Generic`1",TypeAttributes.AutoClass | TypeAttributes.Sealed | TypeAttributes.Public,typeof(object));
var TypeGenerics = typeBuilder.DefineGenericParameters(new[] { "T" });
var methodBuilder = typeBuilder.DefineMethod("GM", MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig);
var methodGenerics = methodBuilder.DefineGenericParameters(new[] { "M" });
methodBuilder.SetSignature(typeof(MethodInfo), null, null, Type.EmptyTypes, null, null);
var ilgenerator = methodBuilder.GetILGenerator();
var typeBuilderClosedOverT = typeBuilder.MakeGenericType(TypeGenerics);
ilgenerator.Emit(OpCodes.Ldtoken, methodBuilder);
ilgenerator.Emit(OpCodes.Ldtoken, typeBuilderClosedOverT);
ilgenerator.Emit(OpCodes.Call, 
    typeof(MethodBase).GetMethod(
        "GetMethodFromHandle", 
        BindingFlags.Public | …
Run Code Online (Sandbox Code Playgroud)

c# il cil reflection.emit

9
推荐指数
1
解决办法
1239
查看次数

如果我在一个封闭的泛型类型上有一个MethodInfo,那么有一种简单的方法来切换这些类型吗?

假设我有类似于methodInfo的方法Nullable<int>.HasValue.无论如何将其转换为Nullable<string>.HasValue

我知道我可以做一个常规的泛型方法,methodInfo.GetGenericMethod()但我没有看到方法为方法中的类型做到这一点,而没有做更多的反射开销.如果我已经有了这个方法,为什么我要再次思考?

有趣的是,这些方法都具有相同的功能MetadataToken,这使得更令人印象深刻的是,不知何故,Module.ResolveMember似乎正在推出正确的方法.

有没有办法做到这一点Module.ResolveMethod?本质上,方法和类型可能都有通用参数,我可能需要切换它们.由于MethodInfo始终表示其令牌相同且令牌表示MethodInfo是该方法的最开放版本.我只需要将它转换为我的类型.

编辑:更多的挖掘,似乎对于类似的东西List<T>.Add,List<int>.Add我检索的元数据令牌实际上存在于我的模块中,而通用定义存在于不同的模块中.

一旦我检索成员,我真的不想做反射,因为很难解决被调用的完全相同的方法.

好吧也许我只是愚蠢,但为什么这不起作用::

var methodinfo = typeof(List<int>).GetMethod("Add");
var handle = methodinfo.MetaDataToken;
var methodinfo2 = methodinfo.Module.ResolveMethod(handle,new []{typeof(string)},null);
Run Code Online (Sandbox Code Playgroud)

为什么methodInfo2说它Add(T)不是Add(string)

c# reflection

8
推荐指数
1
解决办法
3039
查看次数

对于.NET 3.5,如何创建线程安全的get或add缓存?

我已经开始使用一些.NET 3.5代码,并发现以下扩展方法用于缓存::

public static TValue GetOrAdd<TKey, TValue>(this Dictionary<TKey, TValue> @this, TKey key,Func<TKey,TValue> factory,bool useLocking)
{

    TValue value;
    if(!@this.TryGetValue(key,out value))
    {
        if (useLocking)
        {
            lock ((@this as ICollection).SyncRoot)
            {
                if (!@this.TryGetValue(key, out value))
                {
                    @this[key] = value = factory(key);
                }
            }
        }
        else
        {
            @this[key] = value = factory(key);
        }
    }
    return value;
}
Run Code Online (Sandbox Code Playgroud)

有问题的缓存由字符串键和useLocking = true键控.它总是被这种方法访问(没有流浪TryGetValue).使用该SyncRoot属性也没有问题,因为字典是私有的,没有其他地方使用它.双重锁定是危险的,因为字典在写入时不支持读取.虽然技术上没有报告任何问题,因为产品没有发货,我觉得这种方法会导致竞争条件.

  1. 切换Dictionary<,>到a Hashtable.我们将失去类型安全性,但我们将能够支持我们追求的并发模型,(1位作者,多位读者).

  2. 删除外部TryGetValue.这样每次读取都需要锁定.这可能对性能有害,但获得无争议的锁应该相当便宜.

两者都很糟糕.有人有更好的建议吗?如果这是.NET 4代码,我只需将其切换为a ConcurrentDictionary,但我没有这个选项.

c# concurrency

8
推荐指数
1
解决办法
5259
查看次数

为什么投射数组(向量)如此之慢?

我的印象是在.NET中(非转换)非常便宜且快速.但是,这似乎不是阵列的情况.我想在这里做一个非常简单的演员,拿一个T1 []并演员为T2 [].其中T1:T2.

有3种方法可以做到这一点,我称之为以下::

DropCasting: T2[] array2 = array;
CastClass: (T2[])array;
IsInst: array as T2[]; 
Run Code Online (Sandbox Code Playgroud)

我创建了这样做的方法,不幸的是,C#似乎创建了一些相当奇怪的代码,具体取决于它是否是通用的.(如果它的通用DropCasting使用了castclass运算符.在两种情况下,当T1:T2时拒绝发出'as'运算符.

无论如何,我写了一些动态方法,我测试了一些令人惊讶的结果(string [] => object []):

DropCast :    223ms
IsInst   :   3648ms
CastClass:   3732ms
Run Code Online (Sandbox Code Playgroud)

垂直投射比任何一个投射操作员快约18倍.为什么阵列的播放速度如此之慢?对于像string => object这样的普通对象,差异要小得多.

DropCast :    386ms
IsInst   :    611ms
CastClass:    519ms
Run Code Online (Sandbox Code Playgroud)

基准代码如下:

class Program
{
    static readonly String[] strings = Enumerable.Range(0, 10).Select(x => x.ToString()).ToArray();

    static Func<string[], object[]> Dropcast = new Func<Func<string[], object[]>>(
        () =>
        {
            var method = new DynamicMethod("DropCast", typeof(object[]), new[] { typeof(object), typeof(string[]) },true);
            var ilgen = method.GetILGenerator();
            ilgen.Emit(OpCodes.Ldarg_1); …
Run Code Online (Sandbox Code Playgroud)

c# arrays

8
推荐指数
1
解决办法
414
查看次数