我一直在脑子里反复思考,而且我似乎无法想出为什么C#闭包是可变的.如果您不知道究竟发生了什么,这似乎是一种获得意想不到的后果的好方法.
也许一个知识渊博的人可以阐明为什么C#的设计者会允许状态在闭包中改变?
例:
var foo = "hello";
Action bar = () => Console.WriteLine(foo);
bar();
foo = "goodbye";
bar();
Run Code Online (Sandbox Code Playgroud)
这将为第一个呼叫打印"hello",但外部状态在第二个呼叫时改变,打印"再见".更新了闭包的状态以反映局部变量的更改.
考虑我的第一次尝试,F#中的一个简单类型,如下所示:
type Test() =
inherit BaseImplementingNotifyPropertyChangedViaOnPropertyChanged()
let mutable prop: string = null
member this.Prop
with public get() = prop
and public set value =
match value with
| _ when value = prop -> ()
| _ ->
let prop = value
this.OnPropertyChanged("Prop")
Run Code Online (Sandbox Code Playgroud)
现在我通过C#测试它(这个对象正在暴露给C#项目,因此需要明显的C#语义):
[TestMethod]
public void TaskMaster_Test()
{
var target = new FTest();
string propName = null;
target.PropertyChanged += (s, a) => propName = a.PropertyName;
target.Prop = "newString";
Assert.AreEqual("Prop", propName);
Assert.AreEqual("newString", target.Prop);
return;
}
Run Code Online (Sandbox Code Playgroud)
propName如果分配正确,我的F#Setter正在运行,但第二个断言失败,因为底层值prop没有改变.这种方式对我来说很有意义,因为如果我mutable …
我很好奇以下情况是否安全.
我有以下类定义:
class ActiveStatusEffect
{
public:
StatusEffect* effect;
mutable int ReminaingTurns;
ActiveStatusEffect() : ReminaingTurns(0)
{
}
//Other unimportant stuff down here
}
Run Code Online (Sandbox Code Playgroud)
然后我将一组这些存储在std :: set中,如下所示:
struct ASECmp
{
bool operator ()(const StatusEffects::ActiveStatusEffect &eff1, const StatusEffects::ActiveStatusEffect &eff2)
{
return eff1.effect->GetPriority() < eff2.effect->GetPriority();
}
};
std::set<StatusEffects::ActiveStatusEffect, ASECmp> ActiveStatusEffects;
Run Code Online (Sandbox Code Playgroud)
我将RemainingTurns标记为可变,因为我希望能够更改它而不必不断地擦除/插入到集合中.即
void BaseCharacter::Tick(Battles::BattleField &field, int ticks)
{
for (auto effect = ActiveStatusEffects.begin(); effect != ActiveStatusEffects.end();)// ++index)
{
auto next = effect;
++next;
if (effect->effect->HasFlag(StatusEffects::STATUS_FLAGS::TickEffect) && effect->ReminaingTurns > 0)
{
effect->effect->TickCharacter(*this, field, ticks);
--effect->ReminaingTurns;
} …Run Code Online (Sandbox Code Playgroud) 我在以下代码的代码上运行checkstyle时遇到此错误:
@Override
public String[] getDescriptions() {
return DESCRIPTIONS;
}
Run Code Online (Sandbox Code Playgroud)
但是DESCRIPTIONS IS NOT可变.它被定义为:
private static final String[] DESCRIPTIONS = new String[NUM_COLUMNS];
static {
// In a loop assign values to the array.
for (int i = 0; i < NUM_COLUMNS; ++i) {
DESCRIPTIONS[i] = "Some value";
}
}
Run Code Online (Sandbox Code Playgroud)
这是完整的错误消息:
"Returning a reference to a mutable object value stored in one
of the object's fields exposes the internal representation of
the object. If instances are accessed by untrusted code, and
unchecked …Run Code Online (Sandbox Code Playgroud) 我希望有人可以帮助我理解为什么以下代码生成下面的输出.代码来自Simon Marlow的书中的Concurrency章节(链接如下).
基于各种函数的描述,我假设第二个putMVar函数应该被阻塞,因为(i)两个putMVar函数都是同一个线程的一部分,并且(ii)已经分配了一个值.显然情况并非如此.很高兴在这里了解"引擎盖下"发生了什么.
(注意:本书使用do符号,但我更喜欢>>=符号,因为我认为它更直接 - 因此下面的代码版本.)
import Control.Concurrent
main :: IO ()
main = newEmptyMVar >>=
\m -> forkIO (putMVar m 'x' >>= \_ -> putMVar m 'y') >>=
\_ -> takeMVar m >>=
print >>=
\_ -> takeMVar m >>=
print
Run Code Online (Sandbox Code Playgroud)
输出上面的代码:
% ./mvar2
'x'
'y'
Run Code Online (Sandbox Code Playgroud) 我正在制作一个具有非常昂贵的计算导出值的变异结构.所以我想做的是懒惰地计算这个派生值并存储结果,直到结构再次发生变异,此时派生值不再有效,需要重新计算.
如果派生值是生成的属性(如下所示),则始终返回正确的值,但始终重新计算.
如果它是一个懒惰的属性,那么计算只进行一次......永远.因此,一旦结构发生变异,派生值就会出错,并且不会重新计算.此外,如果我从结构中分配一个常量值,我无法访问该属性.
在Swift 1.2中是否有任何可能的解决方案或者我需要提交雷达吗?
struct Struct {
var value: Int
// Option 1: Generated property
var derivedValue: Int {
println("Doing expensive calculation")
return self.value * 2
}
// Option 2: Lazy property
lazy var derivedValue: Int = {
println("Doing expensive calculation")
return self.value * 2
}()
init(value: Int) {
self.value = value
}
mutating func mutate() {
value = random()
}
}
var test = Struct(value: 2)
test.derivedValue
test.derivedValue // If not lazy, expensive calculation is done …Run Code Online (Sandbox Code Playgroud) 我有一个MutableList,我想从中删除一个元素,但我找不到合适的方法.有一种方法可以从ListBuffer这里删除元素:
val x = ListBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9)
x -= 5
Run Code Online (Sandbox Code Playgroud)
我无法找到一个等效的方法MutableList.
有什么区别
let y = &mut 5;
*y += 1;
let x = *y + 1;
Run Code Online (Sandbox Code Playgroud)
和
let mut y = 5;
y += 1;
let x = y + 1;
Run Code Online (Sandbox Code Playgroud)
他们返回相同的结果println!,但我不能决定哪一个更好.
我是Kotlin的新手,需要问一些有关订购的问题MutableList<MyObject>.据我所知,我可以做一个myMutableList.sortBy {it.int}和myMutableList.sortByDescending {it.int}两个Int和String.但回归始终是一个Unit而不是一个MutableList.
我哪里出错了,我该怎么办?
我有以下代码:
struct Baz {
x: usize,
y: usize,
}
struct Bar {
baz: Baz,
}
impl Bar {
fn get_baz_mut(&mut self) -> &mut Baz {
&mut self.baz
}
}
struct Foo {
bar: Bar,
}
impl Foo {
fn foo(&mut self) -> Option<&mut Baz> {
for i in 0..4 {
let baz = self.bar.get_baz_mut();
if baz.x == 0 {
return Some(baz);
}
}
None
}
}
Run Code Online (Sandbox Code Playgroud)
它无法编译:
error[E0499]: cannot borrow `self.bar` as mutable more than once at a time …Run Code Online (Sandbox Code Playgroud)