C# 为什么修改本地数据时收益率返回不起作用?
我正在编写一个VisualStudio扩展,目前正在向编辑器添加边距图示符。我从MS文档中的漫游示例开始: 我的逻辑与示例略有不同,因为我没有分析spans参数给出的文件内容:我已经从以前的分析过程中获得了一组包含缺陷位置的结果。其基本原理是,当且仅当标记尚未呈现时,才生成标记 事实上,我希望避免在用户将新行添加到现有标志之前时错误地渲染新glyph。示例:如果第42行有一个glyph,光标在第41行,并且用户键入了一个新行,则在第42行生成一个新glyph(因为再次调用GetTags方法),同时将上一个glyph移动到第43行 我的代码是:C# 为什么修改本地数据时收益率返回不起作用?,c#,visual-studio-extensions,C#,Visual Studio Extensions,我正在编写一个VisualStudio扩展,目前正在向编辑器添加边距图示符。我从MS文档中的漫游示例开始: 我的逻辑与示例略有不同,因为我没有分析spans参数给出的文件内容:我已经从以前的分析过程中获得了一组包含缺陷位置的结果。其基本原理是,当且仅当标记尚未呈现时,才生成标记 事实上,我希望避免在用户将新行添加到现有标志之前时错误地渲染新glyph。示例:如果第42行有一个glyph,光标在第41行,并且用户键入了一个新行,则在第42行生成一个新glyph(因为再次调用GetTags方法),同
internal class MyDefectTagger : ITagger<MyDefectTag>
{
private IClassifier m_classifier;
private ITextBuffer m_buffer;
internal MyDefectTagger(IClassifier classifier, ITextBuffer buffer)
{
m_classifier = classifier;
m_buffer = buffer;
}
IEnumerable<ITagSpan<MyDefectTag>>
ITagger<MyDefectTag>.GetTags(NormalizedSnapshotSpanCollection spans)
{
var filename = GetFileName(m_buffer);
if (MyModel.Instance == null ||
MyModel.Instance.defectsLocation == null ||
!MyModel.Instance.defectsLocation.ContainsKey(filename))
{
yield break;
}
foreach (SnapshotSpan span in spans)
{
ITextSnapshot textSnapshot = span.Snapshot;
foreach (ITextSnapshotLine textSnapshotLine in textSnapshot.Lines)
{
var line = textSnapshotLine.LineNumber + 1; // Lines start at 1 in VS Editor
if (MyModel.Instance.defectsLocation[filename].ContainsKey(line) &&
!MyModel.Instance.defectsLocation[filename][line].rendered)
{
MyModel.Instance.defectsLocation[filename][line].rendered = true; // YIELD WORKS IF THIS LINE IS COMMENTED OUT
yield return new TagSpan<MyDefectTag>(new SnapshotSpan(textSnapshotLine.Start, 0), new MyDefectTag());
}
}
}
}
}
public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
private string GetFileName(ITextBuffer buffer)
{
buffer.Properties.TryGetProperty(typeof(ITextDocument), out ITextDocument document);
return document?.FilePath;
}
}
内部类MyDefectTagger:ITagger
{
专用IClassizer m_分类器;
私有ITextBuffer Mu buffer;
内部MyDefectTagger(IClassifier分类器、ITextBuffer缓冲区)
{
m_分类器=分类器;
m_buffer=缓冲区;
}
数不清
ITagger.GetTags(规范化快照范围集合范围)
{
var filename=GetFileName(m_缓冲区);
如果(MyModel.Instance==null | |
MyModel.Instance.defectsLocation==null | |
!MyModel.Instance.defectsLocation.ContainsKey(文件名))
{
屈服断裂;
}
foreach(以跨距为单位的快照跨距)
{
ITextSnapshot textSnapshot=span.Snapshot;
foreach(textSnapshot.Lines中的ITextSnapshotLine textSnapshotLine)
{
var line=textSnapshotLine.LineNumber+1;//在VS编辑器中,行从1开始
if(MyModel.Instance.defectsLocation[filename].ContainsKey(行)&&
!MyModel.Instance.defectsLocation[文件名][行].已渲染)
{
MyModel.Instance.defectsLocation[filename][line].rendered=true;//如果这一行被注释掉,则YIELD有效
返回新标记span(新快照span(textSnapshotLine.Start,0),新MyDefectTag());
}
}
}
}
}
公共事件事件处理程序TagsChanged;
私有字符串GetFileName(ITextBuffer)
{
buffer.Properties.TryGetProperty(typeof(ITextDocument),out ITextDocument);
返回文档?.FilePath;
}
}
奇怪的是,当注释掉“rendered=true”行时,yield会正常返回(尽管我得到了false的新glyph)。而在运行line rendered=true时(调试器仍在执行yield指令),产量似乎被阻止
我有什么遗漏吗?使用收益率回报时是否禁止修改本地数据?是否存在一些隐藏的并发问题?谢谢你的帮助 我终于发现,我没有正确扫描normalizedSnapshotSpan集合中给出的行。我错误地使用
foreach(textSnapshot.lines中的ITextSnapshotLine textSnapshotLine)
重新遍历了每个跨度的所有行。事实上,我需要得到与给定跨度相关联的线号,现在它可以工作了:
- 我在每一行上得到了适当的边距图示符,我的分析给了我一个缺陷
- 在一行具有边距图示符之前添加新行时,我不会再获得任何重复
foreach (SnapshotSpan span in spans)
{
var lineNumber= span.Snapshot.GetLineNumberFromPosition(span.Start.Position) + 1;
if (MyModel.Instance.defectsLocation[filename].ContainsKey(lineNumber) &&
!MyModel.Instance.defectsLocation[filename][lineNumber].rendered)
{
//MyModel.Instance.defectsLocation[filename][lineNumber].rendered = true;//Strangely no getting any MyDefectTag displayed when I uncomment this line...
yield return new TagSpan<MyDefectTag>(new SnapshotSpan(span.Start, 0), new MyDefectTag());
}
}
foreach(以跨距为单位的快照跨距)
{
var lineNumber=span.Snapshot.GetLineNumberFromPosition(span.Start.Position)+1;
if(MyModel.Instance.defectsLocation[filename].ContainsKey(行号)&&
!MyModel.Instance.defectsLocation[filename][lineNumber]。已渲染)
{
//MyModel.Instance.defectsLocation[filename][lineNumber].rendered=true;//奇怪的是,当我取消注释此行时,没有显示任何MyDefectTag。。。
返回新标记span(新快照span(span.Start,0),新MyDefectTag());
}
}
我想你的意思是收益率中断
而不是收益率返回空值
。您测试MyModel.Instance
是否为null
,但下次在迭代器上调用MoveNext
时,如果(!MyModel.Instance.defectsLocation…已到达,则可能会导致NRE。嗨!谢谢。我已修复并重试了该问题。我仍然会遇到该问题。除非“rendered=true”指令被注释掉,当调试器仍在执行时,yield return似乎什么也不返回…知道吗?不太清楚“似乎什么都不返回”是什么意思-总的来说,我对您的代码试图做什么以及您观察到的情况感到非常困惑。如果您能将其简化为一个符号,这将使它更容易帮助您。让我解释一下。当我说“似乎什么都不返回”时,我的意思是,在执行“rendered=true”时,我没有得到一个glyph,而我仍然可以看到调试器在执行yield-return指令。至于代码简化,这已经非常简单了:正如我在介绍中所说的,我不需要分析跨度,因为之前已经进行了分析。我得到了一个按文件和行分组的缺陷列表(在defectsLocation中)。我只想为包含缺陷的每一行显示一个边距图示符(在添加新行时不会得到错误的新图示符)。您好,有没有关于此问题的更新?