【问题标题】:Is there a way to call a variable that is been declared in within a foreach function block?有没有办法调用在 foreach 功能块中声明的变量?
【发布时间】:2019-10-22 11:26:44
【问题描述】:

举例

List<BursaryPaymentSplitting> splitAccount = new List<BursaryPaymentSplitting>();

foreach ( var lineItem in splitAccount)
{
    var lineItems = new RemitaSplit { 
        lineItemsId = lineItem.BursaryPaymentSplittingId.ToString(), 
        beneficiaryName = lineItem.AccountName, 
        beneficiaryAccount = lineItem.AccountNumber, 
        bankCode = lineItem.BankCode, 
        beneficiaryAmount = lineItem.Amount.ToString(), 
        deductFeeFrom = lineItem.DeductFeeFrom.ToString() 
    };
}

如何在foreach 功能块之外使用变量lineItems

【问题讨论】:

  • 你不能。如果要使用新对象,请改用 Select 并循环它们
  • 只有在foreach之外声明变量才能使用。如:RemitaSplit lineItems = null;。在 foreach 之后检查 null 以查看变量现在是否包含(有效)值。
  • lineItems 是单个 RemitaSplit 实例。你想用它做什么?无论如何,它在循环之外没有任何意义——即使你把它放在循环之外,它也只会在循环结束后保存最​​后一个循环值。
  • 如果您创建了一个类或结构,您可以将订单项详细信息存储在列表中并访问处理后的结果

标签: c#


【解决方案1】:

在你需要的范围内声明变量。例如:

RemitaSplit lineItems;
foreach (var lineItem in splitAccount)
{
    lineItems = new RemitaSplit { /.../ };
}
// Here you can access the lineItems variable.
// Though it *might* be NULL, your code should account for that.

虽然这里奇怪的是你一遍又一遍地覆盖同一个变量。为什么?你的意思是有一个collection对象而不是一个对象吗?像这样?:

var lineItems = new List<RemitaSplit>();
foreach (var lineItem in splitAccount)
{
    lineItems.Add(new RemitaSplit { /.../ });
}
// Here you can access the lineItems variable.
// And this time it won't be NULL, though it may be an empty collection.

这可能会简化为:

var lineItems = splitAccount.Select(lineItem => new RemitaSplit { /.../ });

在这种情况下如何使用 LINQ 进行简化将取决于您在哪里/如何填充 splitAccount。我假设问题中的示例只是显示该变量类型的人为代码行,因为如果那是确切的代码,那么该循环当然永远不会遍历空列表。

关键是,如果splitAccount 是一个表达式树,它最终将实现来自支持数据源的数据,您可能无法在.Select() 中直接调用new RemitaSplit(),直到您将所有记录具体化为内存,例如.ToList(),可能需要考虑性能。

【讨论】:

  • @Brainiac005 如果我正确理解问题,这就是你应该做的。
【解决方案2】:

lineItems 在整个foreach 中发生变化。

让我们检查一下代码。

foreach ( var lineItem in splitAccount)
{
    var lineItems = new RemitaSplit { 

这翻译成这样:为splitAccount 中的每个元素创建一个名为lineItems 的新单一引用,并为其分配一个新的RemitaSplit 对象。 lineItems 的类型将是 RemitaSplit,不会是 List&lt;RemitaSplit&gt;

解决方案

我怀疑您需要以下内容。

using System.Linq;

(...)

var lineItems = splitAccount.Select( lineItem =>  new RemitaSplit { ... } ).ToList();

foreach

var lineItems = new List<RemitaSplit>();
foreach ( var lineItem in splitAccount)
{
   //item, not items
   var lineItem = new RemitaSplit { 
       lineItemsId = lineItem.BursaryPaymentSplittingId.ToString(),
       (...)
   };
   lineItems.Add(lineItem);
}

编辑:json

我的目标是序列化 lineItems 并发布为 json

using Newtonsoft.Json; 
using System.Linq;

(...)

var lineItems = splitAccount.Select( lineItem => 
    new RemitaSplit { 
        lineItemsId = lineItem.BursaryPaymentSplittingId.ToString(), 
        (...)
        }).ToList();

// Wrapping in an object, as an example, 
// the web doesn't like top level json arrays
// https://stackoverflow.com/questions/3503102/what-are-top-level-json-arrays-and-why-are-they-a-security-risk
// but what you send will be guided by the api the json is sent to. 
var json = JsonConvert.SerializeObject( new { Items = lineItems });

【讨论】:

  • 这是评论,不是答案。
  • 对象lineItems 将保存从splitAccount 获得的所有记录。我的目标是序列化 lineItems 并作为 json 发布到 url,我不能在 foreachcode 块函数中这样做。
  • @Brainiac005 这是一个 RemitaSplit 条目,而不是多个行项目。您要序列化单个条目还是所有 RemitaSplit 条目?
  • var lineItems = splitAccount.Select( lineItem =&gt; new RemitaSplit { ... } ).ToList(); 这有效
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-19
  • 2013-06-27
  • 2021-04-11
  • 1970-01-01
相关资源
最近更新 更多