如果我有一个非常不可变的类型(所有成员都是只读的,如果它们是引用类型成员,那么它们也引用了非常不可变的对象).
我想在类型上实现一个惰性初始化属性,如下所示:
private ReadOnlyCollection<SomeImmutableType> m_PropName = null;
public ReadOnlyCollection<SomeImmutableType> PropName
{
get
{
if(null == m_PropName)
{
ReadOnlyCollection<SomeImmutableType> temp = /* do lazy init */;
m_PropName = temp;
}
return m_PropName;
}
}
Run Code Online (Sandbox Code Playgroud)
据我所知:
m_PropName = temp;
Run Code Online (Sandbox Code Playgroud)
......是线程安全的.我并不担心两个线程同时竞争初始化,因为它很少见,从逻辑角度来看两个结果都是相同的,如果我没有,我宁愿不使用锁至.
这会有用吗?优缺点都有什么?
编辑: 谢谢你的回答.我可能会继续使用锁.但是,我很惊讶没有人提出编译器意识到临时变量是不必要的可能性,只是直接分配给m_PropName.如果是这种情况,则读取线程可能会读取尚未完成构造的对象.编译器是否会阻止这种情况?
(答案似乎表明运行时不会允许这种情况发生.)
编辑: 所以我决定使用由Joe Duffy撰写的这篇文章启发的Interlocked CompareExchange方法.
基本上:
private ReadOnlyCollection<SomeImmutableType> m_PropName = null;
public ReadOnlyCollection<SomeImmutableType> PropName
{
get
{
if(null == m_PropName)
{
ReadOnlyCollection<SomeImmutableType> temp = /* do lazy init */;
System.Threading.Interlocked(ref m_PropName, temp, null);
}
return …Run Code Online (Sandbox Code Playgroud) Android 4.1包括离线语音输入.当您单击弹出键盘上的麦克风时,您可以看到此信息,如果您没有网络连接,它仍然有效.但是,RecognizerIntent当您想要从应用程序进行语音识别时,API 似乎仍然需要网络连接.
是否有用于从我的应用访问Android中新的离线语音输入功能的API?
我有一些代码在Release版本和Debug版本之间表现不同.它在Debug中正常运行,但在Release中不正常.
我有一个函数返回一个ReadOnlyCollection<MyCustomClass>.一节是这样的:
var result = new List<MyCustomClass>();
...
var list1 = this.returnEmptyList();
var list2 = this.returnListWithOneItem();
if (list1.Count == 0 && list2.Count == 0)
{
functionOutVariable = string.Empty;
return result.AsReadOnly();
}
Run Code Online (Sandbox Code Playgroud)
出于故障排除的目的,我简化了代码并以通用方式命名变量,方法returnEmptyList和returnListWithOneItem方法如下所示:
private List<string> returnEmptyList()
{
return new List<string>();
}
private List<string> returnListWithOneItem()
{
return new List<string> {"something"};
}
Run Code Online (Sandbox Code Playgroud)
显然它永远不应该进入if块,因为它list2.Count应该始终为1,但是当我在Release版本中执行它时,它会:
因此,显然有一些优化正在进行,因为您可以看到它list1是不可访问的,并且当单步执行它时执行第416行然后立即跳转到第421行.我应该声明我的解决方案中的所有程序集都使用.NET Framework 4.6.2,并且我正在运行Visual Studio 2017版本15.3.5.
当我改变构建调试和执行这一点,执行管线416,417,和上线418它显示list1.Count为0和list2.Count1,并正确并不能进入if块.
我正在尝试制作一个测试项目来重现这一点,但我不能.我正在寻找任何方法来深究这一点.我不仅仅想要一个让它消失的修复 - …
我用Google搜索并且只收到了一些关于MEF的文章.有人请简要解释一下:
任何一步一步的指导都会有所帮助,谢谢!
我正在使用MVVM将视图绑定到树中的对象.我有一个基类来实现我的树中的项目,并且该基类具有ContextMenu属性:
public IEnumerable<IMenuItem> ContextMenu
{
get
{
return m_ContextMenu;
}
protected set
{
if (m_ContextMenu != value)
{
m_ContextMenu = value;
NotifyPropertyChanged(m_ContextMenuArgs);
}
}
}
private IEnumerable<IMenuItem> m_ContextMenu = null;
static readonly PropertyChangedEventArgs m_ContextMenuArgs =
NotifyPropertyChangedHelper.CreateArgs<AbstractSolutionItem>(o => o.ContextMenu);
Run Code Online (Sandbox Code Playgroud)
绑定到基类(以及所有派生类)的View实现了绑定到该属性的ContextMenu:
<ContextMenu x:Name="contextMenu" ItemsSource="{Binding Path=(local:AbstractSolutionItem.ContextMenu)}"
IsEnabled="{Binding Path=(local:AbstractSolutionItem.ContextMenuEnabled)}"
ItemContainerStyle="{StaticResource contextMenuStyle}"/>
Run Code Online (Sandbox Code Playgroud)
菜单中的每个项目都绑定到IMenuItem对象(菜单项的ViewModel).单击菜单项时,它使用命令在基础对象上执行命令.一切都很好.
但是,一旦命令在IMenuItem类上执行,它有时需要获取用户右键单击的对象的引用以显示上下文菜单(或至少该对象的ViewModel).这是上下文菜单的重点.我应该如何将树项ViewModel的引用传递给MenuItem ViewModel?请注意,某些上下文菜单由树中的许多对象共享.
我有这个静态辅助函数:
public static DependencyObject GetParentObject(DependencyObject child)
{
if (child == null) return null;
ContentElement contentElement = child as ContentElement;
if (contentElement != null)
{
var parent = ContentOperations.GetParent(contentElement);
if (parent != null) return parent;
var fce = contentElement as FrameworkContentElement;
return fce != null ? fce.Parent : null;
}
//if it's not a ContentElement, rely on VisualTreeHelper
return VisualTreeHelper.GetParent(child);
}
Run Code Online (Sandbox Code Playgroud)
它适用于实际应用程序,但我正在尝试为它编写一些单元测试.这是我的第一次尝试:
[Test]
public void GetParentObject_returns_immediate_parent()
{
var contentControl = new ContentControl();
var textBox = new TextBox();
contentControl.BeginInit();
contentControl.Content = textBox; …Run Code Online (Sandbox Code Playgroud) .Last()扩展方法是否考虑了它是否被调用IList?我只是想知道这些之间是否存在显着的性能差异:
IList<int> numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int lastNumber1 = numbers.Last();
int lastNumber2 = numbers[numbers.Count-1];
Run Code Online (Sandbox Code Playgroud)
Intuition告诉我第一个选择是O(n),但第二个是O(1).是否.Last()"聪明"足以尝试将其投射到IList?
我有一个类似这样的ListView:
<ListView
x:Name="SeriesListView"
SnapsToDevicePixels="True"
ItemsSource="{Binding Items}"
BorderBrush="Transparent" BorderThickness="0"
Padding="0" Margin="0"
VerticalContentAlignment="Top"
Background="Purple"
LostFocus="ListView_LostFocus"
>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<local:LDSeriesPanel
SnapsToDevicePixels="True"
MaxWidth="{Binding ElementName=itControl,Path=ActualWidth}"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
MinHeight="{x:Static local:LDSeriesPanel.MIN_HEIGHT}"
MinWidth="{x:Static local:LDSeriesPanel.MIN_WIDTH}"
Margin="0"
Background="Aquamarine"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
Run Code Online (Sandbox Code Playgroud)
当它为空时,我定义的自定义面板的宽度和高度为15 x 15.我可以确认这些是运行时的实际尺寸.但是,ListView本身的尺寸为17 x 17(即面板和ListView之间的一个像素边框).
从自定义面板开始走上树,我得到以下祖先:
如果我将ListView上的填充更改为-1,它会删除边框但会导致其他几个问题.
我希望避免重新模仿整个ListView.其他一切都很好.有没有办法可以通过一种风格删除这个像素边框?
在F#中,构造函数参数自动保存为类中的不可变字段,而不必编写字段声明或将构造函数参数复制到构造函数中的字段.
有没有办法在C#中模仿这个功能?是否存在未来版本的C#无法具备此功能的原因(即现有语言是否存在与此功能冲突的一些基本限制)?
c# ×5
wpf ×3
immutability ×2
.net ×1
android ×1
aslr ×1
border ×1
constructor ×1
contextmenu ×1
definition ×1
f# ×1
lazy-loading ×1
listview ×1
lock-free ×1
mef ×1
mvvm ×1
offline ×1
security ×1
unit-testing ×1