从内部foreach循环到外部foreach循环

时间:2018-03-19 22:09:02

标签: c# foreach

我的代码目前看起来像:

foreach(var request in requestsList){
    foreach(var myVar in request.anotherList){
       if(myVar.hasPermissions()) {
           //do something
       }
    }
}

requestsListList的{​​{1}}。 Request需要连接到数据库,因此我希望最小化对数据库的调用次数。我想将它移到内部myVar.hasPermissions()循环之外,并且每个请求只进行一次调用。

我正在努力实现这样的目标:

foreach

我想要做的就是将foreach(var request in requestsList){ //check for permissions boolean perm = myVar.hasPermissions(); //database call to check permissions foreach(var myVar in request.anotherList){ if(perm) { //do something } } } 移到内部hasPermissions()循环之外。 我面临的问题是我无法访问外部foreach循环中的myVar。迭代遍历列表的循环对我来说很难。

3 个答案:

答案 0 :(得分:0)

如果hasPermission相对静态,即您确定它不会在外循环的运行中发生变化,则可以在检查时缓存权限:

IDictionary<MyVarType,bool> checked = new IDictionary<MyVarType,bool>();
foreach(var request in requestsList){
    foreach(var myVar in request.anotherList) {
        bool permitted;
        if (!checked.TryGetValue(myVar, out permitted)) {
            permitted = myVar.hasPermissions();
            checked.Add(myVar, permitted);
        }
        if(permitted) {
            //do something
        }
    }
}

通过这种方式,您可以根据hasPermissions的不同实例对myVar进行一次调用;所有后续检查都来自checked缓存。

答案 1 :(得分:0)

如果没有关于课程的更多细节,我们只能推测如何最好地解决问题。假设您的anotherList包含类似用户列表的内容,您可以缓存检查结果,这样您就不会再次检查同一个用户。

您可以添加使用Lazy的公共字段来缓存调用hasPermissions的结果 - 您必须在构造函数中初始化它:

public class User {
    public bool hasPermissions() { // check database for permissions
        var ans = false; // ...
        return ans;
    }

    public Lazy<bool> cachedPermissions;

    public User() {
        UncachePermissions();
    }

    public void UncachePermissions() => cachedPermissions = new Lazy<bool>(() => hasPermissions());
}

现在,您可以访问cachedPermissions,而不是调用hasPermissions

foreach (var request in requestsList) {
    foreach (var myVar in request.anotherList) {
        if (myVar.cachedPermissions.Value) {
            //do something
        }
    }
}
每个hasPermissions对象只会调用

User一次。如果单个数据库调用可能存在多个User对象,则需要有关类和方法的更多详细信息。

我添加了UncachePermissions方法来重置缓存,否则您可以使用可能导致问题的hasPermissions的旧值。如果这可能是一个常见问题,您可以在循环中缓存对象外部:

var permissionCache = new Dictionary<User, bool>();

foreach (var request in requestsList) {
    foreach (var myVar in request.anotherList) {
        bool permission;
        if (!permissionCache.TryGetValue(myVar, out permission)) {
            permission = myVar.hasPermissions();
            permissionCache.Add(myVar, permission);
        }
        if (permission) {
            //do something
        }
    }
}

答案 2 :(得分:-1)

我认为你在最上面的循环中称它为最小次数。

如果你以另一种方式思考......

//First get all the 'another' guys:
var allAnother = requestsList.SelectMany(anotherList => anotherList).ToList();

//If you don't have to check them all 
var permitGuys = allAnother.Distinct().Where(a => a.hasPermissions()).ToList();

//Do something with them
foreach(var permitGuy in permitGuys)
{
     //Do something
}