天道酬勤,学无止境

传递给委托时作为参考类型处理的整数(Integer handled as reference type when passed into a delegate)

问题

我本周参加了在荷兰举行的TechDays 2013,并提出了一个有趣的测验问题。 问题是:以下程序的输出是什么。 代码如下所示。

class Program
{
    delegate void Writer();

    static void Main(string[] args)
    {
        var writers = new List<Writer>();
        for (int i = 0; i < 10; i++)
        {
            writers.Add(delegate { Console.WriteLine(i); });
        }

        foreach (Writer writer in writers)
        {
            writer();
        }
    }
}

显然,我给出的答案是错误的。 我争论了一下,因为int是一个值类型,所以传递到Console.WriteLine()的实际值将被复制,因此输出将为0 ... 9。 但是,在这种情况下, i将作为参考类型处理。 正确的答案是它将显示十次。10.谁能解释原因和方式?

回答1

我争论了一下,因为int是一个值类型,所以传递到Console.WriteLine()的实际值将被复制

那是完全正确的。 当您调用WriteLine该值将被复制

那么,您什么时候致电WriteLine ? 它不在for循环中。 您当时并没有编写任何内容,只是创建了一个委托。

直到调用委托时,直到foreach循环,才将变量i中的值复制到堆栈中以调用WriteLine

那么,在foreach循环中i的值是多少? 对于foreach循环的每次迭代,它都是10。

因此,现在您要问:“好吧,在foreach loop, isn't it out of scope i是怎么回事foreach loop, isn't it out of scope吗?好吧,不,不是。这表明是一个“闭包”。当一个匿名方法引用一个变量时该变量的作用域需要持续与该匿名方法一样长的时间,该匿名方法可以持续任何时间。如果根本不做任何特殊的读取,则该变量将是随机垃圾,其中包含碰巧卡在内存中该位置的任何东西。积极确保这种情况不会发生。

那怎么办呢? 它创建一个闭包类; 它是一个类,它将包含许多表示所有已关闭内容的字段。 换句话说,代码将被重构为如下所示:

public class ClosureClass
{
    public int i;

    public void DoStuff()
    {
        Console.WriteLine(i);
    }
}

class Program
{
    delegate void Writer();

    static void Main(string[] args)
    {
        var writers = new List<Writer>();
        ClosureClass closure = new ClosureClass();
        for (closure.i = 0; closure.i < 10; closure.i++)
        {
            writers.Add(closure.DoStuff);
        }

        foreach (Writer writer in writers)
        {
            writer();
        }
    }
}

现在我们都有一个匿名方法的名称(所有匿名方法都由编译器指定名称),并且我们可以确保变量在引用该匿名函数的委托有效期内一直存在。

看着这个重构,我希望这是很清楚,为什么结果是10打印10倍。

回答2

这是因为它是一个捕获的变量。 请注意,这里曾经也有发生foreach ,但在C#5.改变,但是重新编写代码时,你实际上有:

class Program
{
    delegate void Writer();

    class CaptureContext { // generated by the compiler and named something
        public int i;      // truly horrible that is illegal in C#
        public void DoStuff() {
            Console.WriteLine(i);
        }
    }
    static void Main(string[] args)
    {
        var writers = new List<Writer>();
        var ctx = new CaptureContext();
        for (ctx.i = 0; ctx.i < 10; ctx.i++)
        {
            writers.Add(ctx.DoStuff);
        }

        foreach (Writer writer in writers)
        {
            writer();
        }
    }
}

正如你所看到的:只有一个ctx因此只有一个ctx.i ,它是由10你的时间foreachwriters

顺便说一句,如果您想使旧代码正常工作:

for (int tmp = 0; tmp < 10; tmp++)
{
    int i = tmp;
    writers.Add(delegate { Console.WriteLine(i); });
}

基本上,capture-context的作用域与变量处于同一级别。 在这里,变量的作用域循环内,因此会生成:

for (int tmp = 0; tmp < 10; tmp++)
{
    var ctx = new CaptureContext();
    ctx.i = tmp;
    writers.Add(ctx.DoStuff);
}

在这里,每个DoStuff都在不同的捕获上下文实例上,因此具有不同的i

回答3

在您的情况下,委托方法是访问局部变量( for循环索引i )的匿名方法。 就是说,这些都是封闭的东西

由于匿名方法在for循环之后被调用了十次,因此它获得了i的最新值。

访问同一个参考文献的各种形式的简单样本

这是clousure行为的简化版本:

int a = 1;

Action a1 = () => Console.WriteLine(a);
Action a2 = () => Console.WriteLine(a);
Action a3 = () => Console.WriteLine(a);

a = 2;

// This will print 3 times the latest assigned value of `a` (2) variable instead
// of just 1. 
a1();
a2();
a3();

在StackOverflow上检查其他Q&A(.NET中的Clousures?),以获得有关什么是C#/。NET Clousures的更多信息!

回答4

对我来说,通过将旧行为和新行为与本机Action类(而不是自定义Writer进行比较,更容易理解。

在for,foreach变量和局部变量捕获的情况下,在C#5闭包之前捕获相同的变量(而不是变量的值)。 因此,给出代码:

    var anonymousFunctions = new List<Action>();
    var listOfNumbers = Enumerable.Range(0, 10);

    for (int forLoopVariable = 0; forLoopVariable < 10; forLoopVariable++)
    {
        anonymousFunctions.Add(delegate { Console.WriteLine(forLoopVariable); });//outputs 10 every time.
    }

    foreach (Action writer in anonymousFunctions)
    {
        writer();
    }

我们仅看到为变量forLoopVariable设置的最后一个。 但是,使用C#5,已经修改了foreach循环。 现在我们捕获不同的变量。

例如

    anonymousFunctions.Clear();//C# 5 foreach loop captures

    foreach (var i in listOfNumbers)
    {
        anonymousFunctions.Add(delegate { Console.WriteLine(i); });//outputs entire range of numbers
    }

    foreach (Action writer in anonymousFunctions)
    {
        writer();
    }

因此输出更加直观:0,1,2 ...

请注意,这是一项重大更改(尽管假定它是次要的更改)。 这可能就是为什么for循环行为在C#5中保持不变的原因。

标签

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 有人可以用适当的英语提炼出什么是代表?(Can someone distill into proper English what a delegate is?)
    问题 有人可以将代表的含义分解为一个既简短又简短的解释,其中既包含目的,也包含一般利益。 我试图绕过这个问题,只是没有陷入。 回答1 用最简单的术语来说,它本质上是指向方法的指针。 您可以拥有一个保存委托类型的变量(就像您可以拥有一个int类型的int变量一样)。 您可以通过简单地像函数一样调用变量来执行委托指向的方法。 这使您可以拥有可变功能,就像拥有可变数据一样。 您的对象可以接受来自其他对象的委托并调用它们,而不必自己定义所有可能的函数。 当您希望对象根据用户指定的标准执行操作时,这非常方便。 例如,根据用户定义的true / false表达式过滤列表。 您可以让用户指定委托函数,以用作对每个列表项进行评估的过滤器。 回答2 我有一个功能: public long GiveMeTwoTimesTwo() { return 2 * 2; } 此功能很烂。 如果我要3 * 3怎么办? public long GiveMeThreeTimesThree() { return 3 * 3; } 打字太多。 我很懒! public long SquareOf(int n) { return n * n; } 我的SquareOf函数不在乎n是什么。 它可以对传入的任何n正常运行。它不知道n到底是什么,但是它确实知道n是整数。 您不能将"Haha not an integer
  • Java中的函数指针(Function Pointers in Java)
    问题 这可能是常见且琐碎的事情,但是我似乎很难找到一个具体的答案。 在C#中,有一个委托的概念,它与C ++中的函数指针的概念紧密相关。 Java中是否有类似的功能? 考虑到指针的缺失,最好的方法是什么? 而且要明确的是,我们在这里谈论头等舱。 回答1 类似函数指针的功能的Java习惯用法是实现接口的匿名类,例如 Collections.sort(list, new Comparator<MyClass>(){ public int compare(MyClass a, MyClass b) { // compare objects } }); 更新:以上是Java 8之前的Java版本中必需的。现在,我们有更好的替代方法,即lambda: list.sort((a, b) -> a.isGreaterThan(b)); 和方法参考: list.sort(MyClass::isGreaterThan); 回答2 您可以用接口替换函数指针。 假设您要遍历一个集合并对每个元素执行某项操作。 public interface IFunction { public void execute(Object o); } 这是我们可以传递给诸如CollectionUtils2.doFunc(Collection c,IFunction f)的接口。 public static void
  • c#中的引用类型和值类型有什么区别?(What is the difference between a reference type and value type in c#?)
    问题 几个月前有人问我这个问题,我无法详细解释。 C#中的引用类型和值类型有什么区别? 我知道值类型为int , bool , float等,而引用类型为delegate , interface等。还是这是错误的吗? 你能以专业的方式向我解释吗? 回答1 您的示例有点奇怪,因为int , bool和float是特定类型,而接口和委托是类型的类型-就像struct和enum是值类型的类型一样。 我已经在本文中对引用类型和值类型进行了解释。 我很乐意扩展您感到困惑的所有内容。 “ TL; DR”版本将考虑特定类型的变量/表达式的值是什么。 对于值类型,值是信息本身。 对于引用类型,该值是一个引用,该引用可以为null,也可以是导航到包含该信息的对象的方式。 例如,将变量想像成一张纸。 它上面可能写有值“ 5”或“ false”,但它不能有我的房子……它必须要有指向我房子的指示。 这些方向等同于参考。 特别是,两个人可能有不同的纸条,这些纸条包含指向我家的相同方向-如果一个人按照这些指示将我的房子涂成红色,那么第二个人也会看到这种变化。 如果他们俩在纸上都只有我的房子的独立图片,那么一个人给他们的纸上色根本不会改变另一个人的纸。 回答2 值类型: 保存一些值而不是内存地址 例子: 结构 贮存: TL; DR :变量的值存储在清除位置。 例如,局部变量存在于堆栈中
  • 什么是代表? [关闭](What is Delegate? [closed])
    问题 关门了。 这个问题需要更加集中。 它当前不接受答案。 想要改善这个问题吗? 更新问题,使其仅通过编辑此帖子即可将重点放在一个问题上。 7年前关闭。 改善这个问题 我很困惑代表的实际角色是什么? 我在面试中曾多次被问到这个问题,但我认为面试官对我的回答并不满意。 有人能用一个实例告诉我最好的定义吗? 回答1 我喜欢将委托视为“指向函数的指针”。 这可以追溯到C天,但是这个想法仍然成立。 这个想法是,您需要能够调用一段代码,但是要在运行时才知道要调用的那段代码。 因此,您可以为此目的使用“代表”。 委托对于事件处理程序之类的事情派上用场,例如,您可以根据不同的事件来执行不同的事情。 这是您可以查看的C#参考: 例如,在C#中,我们有一个想要做的计算,并且想使用一种直到运行时才知道的不同的计算方法。 因此,我们可能有两种类似的计算方法: public static double CalcTotalMethod1(double amt) { return amt * .014; } public static double CalcTotalMethod2(double amt) { return amt * .056 + 42.43; } 我们可以这样声明一个委托签名: public delegate double calcTotalDelegate(double amt)
  • Java和C#中的int和Integer有什么区别?(What is the difference between an int and an Integer in Java and C#?)
    问题 当我遇到Joel Spolsky时,我读的是《更多关于软件的Joel》,这是关于某种特定类型的程序员的一些知识,他们了解Java / C#(面向对象的编程语言)中的int和Integer之间的区别。 那么区别是什么呢? 回答1 在Java中, “ int”类型是基元,而“ Integer”类型是对象。 在C#中, “ int”类型与System.Int32相同,并且是一个值类型(即,更像Java的“ int”)。 可以将一个整数(就像其他任何值类型一样)装箱(“包装”)到一个对象中。 对象和基元之间的差异在一定程度上超出了此问题的范围,但可以总结一下: 对象为多态提供了便利,通过引用传递(或更准确地说,通过值传递引用),并从堆中分配对象。 相反,基元是不可变的类型,它们按值传递,并且通常是从堆栈中分配的。 回答2 好吧,在Java中,一个int是一个原语,而一个Integer是一个Object。 意思是,如果您创建了一个新的Integer: Integer i = new Integer(6); 您可以在i上调用一些方法: String s = i.toString();//sets s the string representation of i 而使用int的情况: int i = 6; 您不能在其上调用任何方法,因为它只是一个原始类型。 所以: String s = i
  • Java是“按引用传递”还是“按值传递”?(Is Java “pass-by-reference” or “pass-by-value”?)
    问题 我一直认为Java使用传递引用。 但是,我已经看到一些博客文章(例如,该博客)声称不是(博客文章中说Java使用值传递)。 我不认为我能理解他们的区别。 有什么解释? 回答1 Java总是按值传递。 不幸的是,我们根本不处理任何对象,而是处理称为引用的对象句柄(当然是通过值传递) 。 选择的术语和语义很容易使许多初学者感到困惑。 它是这样的: public static void main(String[] args) { Dog aDog = new Dog("Max"); Dog oldDog = aDog; // we pass the object to foo foo(aDog); // aDog variable is still pointing to the "Max" dog when foo(...) returns aDog.getName().equals("Max"); // true aDog.getName().equals("Fifi"); // false aDog == oldDog; // true } public static void foo(Dog d) { d.getName().equals("Max"); // true // change d inside of foo() to point to a new Dog
  • Python函数如何处理您传入的参数类型?(How do Python functions handle the types of the parameters that you pass in?)
    问题 除非我没有记错,否则在Python中创建函数的工作方式如下: def my_func(param1, param2): # stuff 但是,您实际上并没有给出这些参数的类型。 另外,如果我还记得,Python是一种强类型语言,因此,似乎Python不应让您传递与函数创建者所期望的类型不同的参数。 但是,Python如何知道函数的用户正在传递正确的类型? 假定函数实际上使用了参数,那么如果类型错误,程序会死掉吗? 您必须指定类型吗? 回答1 Python是强类型的,因为每个对象都有一个类型,每个对象都知道其类型,不可能无意或有意地使用“好像”它是不同类型的对象的对象,并且对该对象的所有基本操作都是委托给它的类型。 这与名称无关。 Python中的名称没有“具有类型”:如果并且在定义名称时,该名称指向一个对象,并且该对象确实具有一个类型(但是实际上并不会在名称上强制使用一种类型:a名称是一个名称)。 Python中的名称可以很好地在不同时间引用不同的对象(就像大多数编程语言一样,尽管不是全部)-并且名称不受任何限制,因此,如果曾经引用过X类型的对象,这样一来,就永远只能引用其他类型为X的对象。名称的约束不是“强类型”概念的一部分,尽管一些静态类型的爱好者(名称确实受到约束,并且在静态AKA中会编译-时间,时尚也是如此)请勿以这种方式滥用该术语。 回答2
  • 了解C#中的事件和事件处理程序(Understanding events and event handlers in C#)
    问题 我了解事件的目的,尤其是在创建用户界面的上下文中。 我认为这是创建事件的原型: public void EventName(object sender, EventArgs e); 事件处理程序做什么,为什么需要它们,以及如何创建事件处理程序? 回答1 要了解事件处理程序,您需要了解委托。 在C#中,您可以将委托视为方法的指针(或引用)。 这很有用,因为指针可以作为值传递。 代表的中心概念是其签名或形状。 即(1)返回类型和(2)输入参数。 例如,如果我们创建一个委托void MyDelegate(object sender, EventArgs e) ,则它只能指向返回void并采用一个object和EventArgs 。 有点像方孔和方钉。 因此,我们说这些方法与委托具有相同的签名或形状。 因此,了解了如何创建对方法的引用之后,我们来考虑事件的目的:当系统中其他地方发生事件时,我们希望使某些代码得以执行-或“处理事件”。 为此,我们为要执行的代码创建特定的方法。 事件和要执行的方法之间的粘合是委托。 该事件必须在内部存储指向引发该事件时要调用的方法的指针的“列表”。*当然,要能够调用方法,我们需要知道要传递给它的参数! 我们使用委托作为事件与将要调用的所有特定方法之间的“契约”。 因此,默认的EventHandler (以及许多类似的EventHandler
  • 如何在animationDidStop委托中标识CAAnimation?(How to identify CAAnimation within the animationDidStop delegate?)
    问题 我遇到了一个问题,即我有一系列重叠的CATransition / CAAnimation序列,当动画停止时,所有这些序列都需要执行自定义操作,但是我只需要一个animationDidStop委托处理程序。 但是,我有一个问题,似乎没有一种方法可以唯一地标识animationDidStop委托中的每个CATransition / CAAnimation。 我通过作为CAAnimation的一部分公开的键/值系统解决了这个问题。 启动动画时,请使用CATransition / CAAnimation上的setValue方法来设置您的标识符和值,以便在animationDidStop触发时使用: -(void)volumeControlFadeToOrange { CATransition* volumeControlAnimation = [CATransition animation]; [volumeControlAnimation setType:kCATransitionFade]; [volumeControlAnimation setSubtype:kCATransitionFromTop]; [volumeControlAnimation setDelegate:self]; [volumeControlLevel setBackgroundImage
  • 引用Java8中具有不同参数的方法(Reference to methods with different parameters in Java8)
    问题 我想知道带有方法引用和功能接口的所有这些东西如何在较低级别上工作。 最简单的例子是我们有一些列表 List<String> list = new ArrayList<>(); list.add("b"); list.add("a"); list.add("c"): 现在我们要使用Collections类对其进行排序,因此我们可以调用: Collections.sort(list, String::compareToIgnoreCase); 但是,如果我们定义自定义比较器,则可能类似于: Comparator<String> customComp = new MyCustomOrderComparator<>(); Collections.sort(list, customComp::compare); 问题在于Collections.sort具有两个参数:List和Comparator。 由于Comparator是功能性接口,因此可以将其替换为具有相同签名(参数和返回类型)的lambda表达式或方法引用。 那么,我们如何也可以传递对compareTo的引用,后者仅接受一个参数,并且这些方法的签名不匹配? 方法引用如何在Java8中翻译? 回答1 从Oracle方法参考教程: 引用特定类型的任意对象的实例方法以下是对特定类型的任意对象的实例方法的引用示例: String[]
  • 为什么事件处理程序的返回类型始终为void?(Why do event handlers always have a return type of void?)
    问题 嘿,我想知道为什么返回的事件类型如 private void button1_Click(object sender, EventArgs e) 永远是空的? 它也可以返回任何其他值吗? 回答1 事件处理程序签名(即返回类型以及它采用的参数的数量和类型)由用于定义事件的delegate的签名确定。 因此,示例中Button的Click事件不支持任何返回值。 通常,您不希望从事件处理程序中返回一个值作为函数返回值,因为一个事件可以有多个订阅者,并且每个订阅者都将独立于其他其他处理程序返回一个返回值,并且需要特殊的事件触发代码来确定要执行的操作。使用所有返回值。 通常,如果您需要从事件处理程序进行回传,则EventArgs结构将包含该处理程序可以更新的成员,并且每个处理程序都将有机会查看值并进行相应更新,并且触发事件的代码仅需要对此做出反应结构中的最终值。 回答2 一个事件可以有一个返回值。 但这是BCL准则,返回void(并具有2个参数)。 使用事件的多播属性时,返回值会使您感到困惑。 返回的值是最后执行的处理程序的值。 所有其他已订阅处理程序的返回都将丢失,并且由于将事件用于解耦,因此您对它们的执行顺序没有太多控制。 这使得返回值非常不切实际。 BCL的另一种实践是通过EventArgs后代的可写属性(例如Window.Closing事件的Cancel属性)共享和返回信息。
  • int []是引用类型还是值类型?(Is int[] a reference type or a value type?)
    问题 我知道一个int是一个值类型,但是值类型的数组是什么? 参考类型? 值类型? 我想将数组传递给函数以检查某些内容。 我应该只传递数组,因为它将只传递它的引用,还是应该将它作为ref传递? 回答1 数组是使您可以将多个项目视为一个集合的机制。 Microsoft®.NET公共语言运行时(CLR)支持一维数组,多维数组和锯齿状数组(数组的数组)。 所有数组类型都隐式派生自System.Array,而System.Array本身派生自System.Object。 这意味着所有数组始终是在托管堆上分配的引用类型,并且您的应用程序的变量包含对数组的引用,而不是数组本身。 https://msdn.microsoft.com/zh-CN/library/bb985948.aspx 回答2 对于引用类型与值类型的最简单测试是,引用类型可以为null ,而值类型不能为null 。 回答3 数组(甚至是像int这样的值类型)都是C#中的引用类型。 http://msdn.microsoft.com/zh-CN/library/aa288453(VS.71).aspx: 在C#中,数组实际上是对象。 System.Array是所有数组类型的抽象基类型。 回答4 首先,我想告诉您Array是引用类型。 为什么? 我在这里解释一个例子。 例子: int val = 0; // this is a
  • Red Team后漏洞利用秘籍:如何使用C#语言实现系统调用
    0x00 前言 在过去的一年中,安全社区(特别是红方运营团队和蓝方防御团队)持续关注Windows恶意软件如何实现后漏洞利用活动,以及如何绕过终端检测与响应(EDR)设备。 现在,对于某些防御人员来说,这种技术的使用还是比较陌生的,但对于攻击者来说却并非如此。许多年来,很多恶意软件作者、开发人员甚至是游戏破解者都在尝试利用系统调用和内存加载。其最初目标是绕过某些通过反病毒和反作弊引擎之类的工具来实现的限制和安全措施。 在一些文章中,已经介绍过如何利用这些系统调用技术,例如:如何绕过EDR的内存保护、关于挂钩的介绍、结合直接系统调用和sRDI绕过AV或EDR等等。作为红队成员,这些技术的使用对于秘密行动来说至关重要,因为它们使我们能够在网络范围内进行后漏洞利用活动,同时又能够避开监控。 这些技术的实现大部分都是在C++中完成的,以便轻松地与Win32 API和系统进行交互。但是,使用C++来编写工具存在着一个缺点,就是我们将代码编译后,总会得到一个EXE文件。为了实现秘密行动的目标,作为红队运营者来说更倾向于避免接触磁盘,我们不想盲目地把文件复制到系统上并执行。因此,我们倾向于寻找一种方法,将这些工具以一种更安全的方式注入到内存中。 尽管在任何恶意软件相关的领域,C++都是一种非常不错的语言,但当我在尝试编写一些后漏洞利用工具时,我开始认真考虑将系统调用集成到C#之中
  • 何时使用引用与指针(When to use references vs. pointers)
    问题 我了解指针与引用的语法和一般语义,但是我应该如何确定何时在API中使用引用或指针更合适? 自然地,有些情况需要一个或另一个( operator++需要一个引用参数),但是总的来说,我发现我更喜欢使用指针(和const指针),因为语法很清楚地表明,变量是以破坏性方式传递的。 例如下面的代码: void add_one(int& n) { n += 1; } void add_one(int* const n) { *n += 1; } int main() { int a = 0; add_one(a); // Not clear that a may be modified add_one(&a); // 'a' is clearly being passed destructively } 使用指针,它总是(更)明显地发生了什么事情,因此对于那些关注清晰度的API之类的指针来说,指针比引用更合适吗? 这是否意味着仅在必要时才使用引用(例如operator++ )? 两者之间是否存在性能问题? 编辑(已过时): 除了允许使用NULL值并处理原始数组外,选择还取决于个人喜好。 我接受了下面引用Google C ++样式指南的答案,因为他们提出了这样的观点:“引用可能会造成混淆,因为引用具有值语法但具有指针语义。” 由于清理不应该为NULL的指针参数需要进行额外的工作(例如add
  • 浏览器如何处理高度和宽度的非整数值?(How do browsers deal with non-integer values for height and width?)
    问题 当给浏览器指定不是整数值的元素的宽度和高度时,它们如何处理? 特别是, 非整数值在什么阶段取整? 它们是舍入到最接近的整数还是截断它们? 当容器的子项具有非整数尺寸时,是否会出现子项长度或高度之和不等于父元素的内部宽度/高度的情况? 提供的非整数维度与基于百分比的维度的非整数结果的处理方式是否不同? 填充和边距的非整数值又如何呢? 编辑:是执行此舍入的浏览器,还是操作系统? 如果是操作系统,是否会造成浏览器“认为”项目大于其绘制区域的条件,并且是否对父容器的大小产生问题? 回答1 断言 浏览器旨在处理小于一个像素的浮点数和值。 要查看显示浏览器在计算中使用浮点数的简单示例,请创建宽度为3%的项,并在调整大小后在Chrome开发人员工具中查看其计算出的属性。 您应该会看到类似以下内容的内容: 在物理显示器(CRT,传统LCD)中将一个像素映射到一个像素的显示器无法精确呈现“ 35.296875”。 但是,较新的高密度显示器使用的比率不同于1-1,并且该分数值可以在概念上用于提供更高的精度。 即使在低密度显示器上,分数值也可以为子像素渲染提供提示,该渲染使用像素的红色,绿色和蓝色成分使对象的边缘显得比使用整个像素值时要平滑。 但究竟什么浏览器会做这样的数字是不是很预见的。 您(当前)不能要求浏览器制作一个31.5像素宽的框,并期望获得一致甚至有意义的结果。
  • 按引用传递与按值传递有什么区别?(What's the difference between passing by reference vs. passing by value?)
    问题 之间有什么区别 通过引用传递的参数通过值传递的参数? 请给我一些例子吗? 回答1 首先,在CS理论中定义的“按值传递与按引用传递”的区别现在已过时,因为最初定义为“按引用传递”的技术此后不再受欢迎,现在很少使用。 1个 较新的语言2倾向于使用不同的(但相似的)技术对来达到相同的效果(见下文),这是造成混淆的主要原因。 造成混淆的第二个原因是,在“通过引用传递”中,“引用”的含义比通用术语“引用”的含义要窄(因为该短语早于它)。 现在,真实的定义是: 通过引用传递参数时,调用者和被调用者对该参数使用相同的变量。 如果被调用方修改了参数变量,则效果对调用方的变量可见。 通过value传递参数时,调用方和被调用方将具有两个具有相同值的独立变量。 如果被调用方修改了参数变量,则该效果对调用方不可见。 在此定义中要注意的是: 这里的“变量”是指调用方的(本地或全局)变量本身-即,如果我通过引用传递局部变量并将其分配给它,则我将更改调用方的变量本身,而不是例如它是指针时指向的变量。 现在,这被认为是不好的做法(作为隐式依赖)。 因此,几乎所有较新的语言都是专有的或几乎专有的值传递。 现在,在函数不能返回多个值的语言中,按引用传递主要以“输出/输入参数”的形式使用。 “通过引用传递”中“引用”的含义。 与一般“参考”一词的区别在于,该“参考”是暂时的和隐含的。 被呼叫者基本上得到的是一个
  • C#3.0泛型类型推断-将委托作为函数参数传递(C# 3.0 generic type inference - passing a delegate as a function parameter)
    问题 我想知道为什么当C#3.0编译器可以隐式为同一方法创建委托时,将其作为参数传递给泛型函数时,为什么无法推断方法的类型。 这是一个例子: class Test { static void foo(int x) { } static void bar<T>(Action<T> f) { } static void test() { Action<int> f = foo; // I can do this bar(f); // and then do this bar(foo); // but this does not work } } 我以为我可以将foo传递给bar并让编译器从传递的函数签名中推断Action<T>的类型,但这不起作用。 但是我可以从foo创建一个Action<int>而不进行强制转换,所以编译器不能通过类型推断也不能做同样的事情吗? 回答1 也许这样可以使它更清晰: public class SomeClass { static void foo(int x) { } static void foo(string s) { } static void bar<T>(Action<T> f){} static void barz(Action<int> f) { } static void test() { Action<int> f = foo; bar
  • Java中Integer和int有什么区别?(What is the difference between Integer and int in Java?)
    问题 例如,为什么可以这样做: int n = 9; 但不是: Integer n = 9; 您可以执行以下操作: Integer.parseInt("1"); 但不是: int.parseInt("1"); 回答1 int是原始类型。 int类型的变量存储要表示的整数的实际二进制值。 int.parseInt("1")没有意义,因为int不是类,因此没有任何方法。 Integer是一个类,与Java语言中的其他类没有什么不同。 类型的变量Integer存储引用Integer对象,就像任何其它参考(对象)类型。 Integer.parseInt("1")是对Integer类的静态方法parseInt的调用(请注意,此方法实际上返回一个int而不是Integer )。 更具体地说, Integer是具有单个类型为int字段的类。 此类用于需要将int像任何其他对象一样对待的地方,例如在通用类型或需要可为空的情况下。 请注意,Java中的每个基本类型都有一个等效的包装器类: byte有Byte short有Short int具有Integer long Long boolean具有Boolean char具有Character float有Float double有Double 包装器类从Object类继承,而原始类则没有。 因此,它可以在带有对象引用或泛型的集合中使用。 从Java
  • 使用Segue在View Controller之间传递数据(Passing data between View Controllers using Segue)
    问题 我是iOS新手。 我在ViewControllers之间传递数据时遇到问题。 我有三个viewControllers(view_1,view_2和view_3)。 这是我的设置:- 选择view_1 推动view_2 推view_3 我想将'view_1'的ViewController参考(id)发送到'view_3'。 所以我在include "view_3"中include "view_3" ,并将值设置为“ view_3”变量(使用view_3 *v3=[[view_3 alloc] init ]; v3.reference=self; )。 在控制台中,它显示: 视图控制器:-; <ViewController:0x89e9540> 在“ view_1”中,但在“ view_3”中,在控制台中显示 视图控制器(空) 但是,当我使用“ view_2”传递此数据时,它的工作原理。 但是如何? 我想知道这种行为,并且有解决方案吗? 请帮忙。 回答1 当触发segue时,“将数据传递到目标控制器”将通过重写prepareForSegue:sender:方法来实现。 通常,您将数据而不是源视图控制器传递给目标视图控制器。 “数据”可能是您的应用程序“模型”的某个方面。 这是一个类似“用户”的对象,或者是一个包含“用户”的数组,等等。 目标视图控制器不应对源视图控制器有任何了解。
  • 代表和事件之间有什么区别?(What are the differences between delegates and events?)
    问题 代表和事件之间有什么区别? 两者都不持有对可以执行的功能的引用吗? 回答1 事件声明在委托实例上添加了一层抽象和保护。 此保护可防止委托的客户端重置委托及其调用列表,并且仅允许在调用列表中添加或删除目标。 回答2 要了解差异,您可以看一下以下两个示例 带有委托的示例(在这种情况下,是一个Action-这是一种不返回值的委托) public class Animal { public Action Run {get; set;} public void RaiseEvent() { if (Run != null) { Run(); } } } 要使用委托,您应该执行以下操作: Animal animal= new Animal(); animal.Run += () => Console.WriteLine("I'm running"); animal.Run += () => Console.WriteLine("I'm still running") ; animal.RaiseEvent(); 这段代码效果很好,但是您可能会遇到一些薄弱环节。 例如,如果我这样写: animal.Run += () => Console.WriteLine("I'm running"); animal.Run += () => Console.WriteLine("I'm still