Configurator CSharp: .Max() on list

I am working on my configurator, and I want to use the .Max() function to get the maximum value of a decimal list. When I attempt to do this, I get an error saying:
" ‘List’ does not contain a definition for ‘Max’ and no accessible extension method ‘Max’ accepting a first argument of type ‘List’ could be found (are you missing a using directive or an assembly reference?)"

I tried to add linq to the expression by putting “using System.Linq;” at the top of it, but that gives me a different error saying the following:
" Identifier expected
‘System.Linq’ is a namespace but is used like a type
You must provide an initializer in a fixed or using statement declaration "

Am I doing something wrong here? Or does the configurator expression editor not support max/linq? I originally had this code find the max by just doing a for loop, but I want to make the code look and perform better.

An example of how you are trying to accomplish this from your code would be more helpful than just the error provided. That being said, you can use IEnumerable against a list to find a max item. There are other ways as well, but without more information it is difficult to know which direction to point you.

To help the community provide the best answer, could you include as much of the information below as you can? Your question appears to be lacking some much needed context


  • Epicor Version
  • Deployment Type (Cloud, On Prem, 3rd Party Cloud etc)
  • The business problem you’re trying to solve
  • What you’ve already tried
  • Is this a Kinetic UX (Web) or Epicor Classic issue?
  • Is it related to a Method Directive, Data Directive, Function, BAQ, UBAQ, Configurator, etc.?
  • Any screenshots, error messages, or logs.
  • Any code you’ve written (or borrowed , make sure it is property formatted)
    ```
    code here
    ```
  • Steps to reproduce the issue

For tips on how to ask questions effectively, check out this guide:
Tips for Asking Questions on the Forum
clippy-hi

1 Like

Version: Kinetic 2025.1.11 Cloud. Working in configurator CSharp editor.

My configurator code is using for loops to find the maximum/minimum value in a list. What I want to do is just use the .Max() function to get the maximum value in the list. I tried to just put in listWidth.Max() but that has an error saying:

‘List’ does not contain a definition for ‘Max’ and no accessible extension method ‘Max’ accepting a first argument of type ‘List’ could be found (are you missing a using directive or an assembly reference?)

I thought I just had to add using System.Linq to the top of the expression, but that gives the following error:

Identifier expected
‘System.Linq’ is a namespace but is used like a type
You must provide an initializer in a fixed or using statement declaration

Am I supposed to be doing something different to use the max/min functions? Does configurator even allow these functions?

Code:

var listWidth = new List<decimal>
{
  Inputs.nmbMaterialWidth.Value, Inputs.nmbMaterialWidth2.Value, Inputs.nmbMaterialWidth3.Value, 
  Inputs.nmbMaterialWidth4.Value, Inputs.nmbMaterialWidth5.Value, Inputs.nmbMaterialWidth6.Value,
  Inputs.nmbMaterialWidth7.Value, Inputs.nmbMaterialWidth8.Value, Inputs.nmbMaterialWidth9.Value, 
  Inputs.nmbMaterialWidth10.Value
};

var listLength = new List<decimal>
{
  Inputs.nmbLengthIn1.Value, Inputs.nmbLengthIn2.Value, Inputs.nmbLengthIn3.Value, 
  Inputs.nmbLengthIn4.Value, Inputs.nmbLengthIn5.Value, Inputs.nmbLengthIn6.Value, 
  Inputs.nmbLengthIn7.Value, Inputs.nmbLengthIn8.Value, Inputs.nmbLengthIn9.Value, 
  Inputs.nmbLengthIn10.Value
};

decimal tempminwidth = decimal.MaxValue;
decimal tempminlength = decimal.MaxValue; 


//gets min width of the list
foreach (decimal numWMX in listWidth)
{
    if(numWMX != 0 && numWMX < tempminwidth)
    {
      tempminwidth = numWMX;
      Inputs.nmbMinWidth.Value = tempminwidth;
    }
}

//gets max width of the list
foreach (decimal i in listWidth)
{
  if (i > Inputs.nmbMaxWidth.Value)
  {
    Inputs.nmbMaxWidth.Value = i;
  }
}

//gets max length of the list
foreach (decimal j in listLength)
{
    if (j > Inputs.nmbMaxLength.Value)
    {
        Inputs.nmbMaxLength.Value = j;
    }
}

//gets min length of the list
foreach (decimal numWMN in listLength)
{
    if(numWMN != 0 && numWMN < tempminlength)
    {
      tempminlength = numWMN;
      Inputs.nmbMinLength.Value = tempminlength;
    }
}

Sorry for the delay in responding.

I’m not totally sure about cloud, but you need to ensure your references include access to this:

// System.Linq.Enumerable
using System.Collections.Generic;

/// <summary>Returns the maximum value in a sequence of <see cref="T:System.Decimal" /> values.</summary>
/// <param name="source">A sequence of <see cref="T:System.Decimal" /> values to determine the maximum value of.</param>
/// <returns>The maximum value in the sequence.</returns>
/// <exception cref="T:System.ArgumentNullException">
///         <paramref name="source" /> is <see langword="null" />.</exception>
/// <exception cref="T:System.InvalidOperationException">
///         <paramref name="source" /> contains no elements.</exception>
[__DynamicallyInvokable]
public static decimal Max(this IEnumerable<decimal> source)

You could get your values like this as long as the appropriate references exist:

Inputs.nmbMaxLength.Value = System.Linq.Enumerable.Max(listLength);

It looks like those references don’t exist in the cloud environment. When I put in the last bit of code you provided, I get an error saying:

 The type name 'Enumerable' could not be found in the namespace 'System.Linq'. This type has been forwarded to assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' Consider adding a reference to that assembly.

This is not a big deal, I will just use the for loops I currently have. Thank you for your help though.

1 Like

The List class is in the System.Collections.Generic library, so that shouldn’t be the problem. There could be some weirdness going on in interpreting what your List is. Could you try adding .AsEnumerable() between your List and the Max method?
Something like myList.AsEnumerable().Max(x => x.field) to explicitly tell the compiler that you want to access the enumerable methods of your List…

1 Like

I tried this but I got an error saying
‘List’ does not contain a definition for ‘AsEnumerable’ and no accessible extension method ‘AsEnumerable’ accepting a first argument of type ‘List’ could be found (are you missing a using directive or an assembly reference?)

Okay, same error for two methods that should be available to a List object.

I neglected to notice that you’re in the Configurator, but why would that limit what methods are available? Unless they (Epicor) implemented their own List class that does not have or expose those methods for whatever reason, but that almost seems malicious…

1 Like

Ok, you can always roll your own MinMax functions then :slight_smile:

Func<List<decimal>,decimal?> listMax = (source) =>
{
	if (source == null)
	{
		throw new ArgumentNullException(nameof(source), "Data cannot be null or empty.");
	}
	decimal num = default(decimal);
	bool flag = false;
	foreach (decimal item in source)
	{
		if (flag)
		{
			if (item > num)
			{
				num = item;
			}
		}
		else
		{
			num = item;
			flag = true;
		}
	}
	if (flag)
	{
		return num;
	}
	throw new ArgumentOutOfRangeException(nameof(source), "The list cannot be null or empty for this operation.");
};

Func<List<decimal>, decimal?> listMin = (source) =>
 {
	if (source == null)
	 {
		 throw new ArgumentNullException(nameof(source), "Data cannot be null or empty.");
	 }
	 decimal? num = null;
	 foreach (decimal? item in source)
	{
		if (!num.HasValue || item < num)
		{
			num = item;
		}
	}
	return num;
 };


// Sample data with pretend Inputs
var listWidth = new List<decimal>
{
  10m,12m,9.1m,1.7m
};

var listLength = new List<decimal>
{
  10m,13m,9.1m,3.7m
};

// Pretend Inputs to set
dynamic Inputs = new System.Dynamic.ExpandoObject();

Inputs.nmbMinWidth = new System.Dynamic.ExpandoObject();
Inputs.nmbMinLength = new System.Dynamic.ExpandoObject();
Inputs.nmbMaxWidth = new System.Dynamic.ExpandoObject();
Inputs.nmbMaxLength = new System.Dynamic.ExpandoObject();

Inputs.nmbMinWidth.Value = (decimal?)null;
Inputs.nmbMinLength.Value = (decimal?)null;
Inputs.nmbMaxWidth.Value = (decimal?)null;
Inputs.nmbMaxLength.Value = (decimal?)null;

/* your Code I created dummy data above
var listWidth = new List<decimal>
{
  Inputs.nmbMaterialWidth.Value, Inputs.nmbMaterialWidth2.Value, Inputs.nmbMaterialWidth3.Value,
  Inputs.nmbMaterialWidth4.Value, Inputs.nmbMaterialWidth5.Value, Inputs.nmbMaterialWidth6.Value,
  Inputs.nmbMaterialWidth7.Value, Inputs.nmbMaterialWidth8.Value, Inputs.nmbMaterialWidth9.Value,
  Inputs.nmbMaterialWidth10.Value
};

var listLength = new List<decimal>
{
  Inputs.nmbLengthIn1.Value, Inputs.nmbLengthIn2.Value, Inputs.nmbLengthIn3.Value,
  Inputs.nmbLengthIn4.Value, Inputs.nmbLengthIn5.Value, Inputs.nmbLengthIn6.Value,
  Inputs.nmbLengthIn7.Value, Inputs.nmbLengthIn8.Value, Inputs.nmbLengthIn9.Value,
  Inputs.nmbLengthIn10.Value
};

*/

decimal tempminwidth = decimal.MaxValue;
decimal tempminlength = decimal.MaxValue;

// Self Func's to get values you want
Inputs.nmbMaxWidth.Value = listMax(listWidth);
Inputs.nmbMaxLength.Value = listMax(listLength);
Inputs.nmbMinWidth.Value = listMin(listWidth);
Inputs.nmbMinLength.Value = listMin(listLength);

/* Your loops code
//gets min width of the list
foreach (decimal numWMX in listWidth)
{
	if (numWMX != 0 && numWMX < tempminwidth)
	{
		tempminwidth = numWMX;
		Inputs.nmbMinWidth.Value = tempminwidth;
	}
}

//gets max width of the list
foreach (decimal i in listWidth)
{
	if (i > Inputs.nmbMaxWidth.Value)
	{
		Inputs.nmbMaxWidth.Value = i;
	}
}

//gets max length of the list
foreach (decimal j in listLength)
{
	if (j > Inputs.nmbMaxLength.Value)
	{
		Inputs.nmbMaxLength.Value = j;
	}
}

//gets min length of the list
foreach (decimal numWMN in listLength)
{
	if (numWMN != 0 && numWMN < tempminlength)
	{
		tempminlength = numWMN;
		Inputs.nmbMinLength.Value = tempminlength;
	}
};

*/

Output


Inputs.nmbMaxWidth.Value
12 


Inputs.nmbMaxLength.Value
13 


Inputs.nmbMinWidth.Value
1.7 


Inputs.nmbMinLength.Value
3.7 

P.S. (EDIT)
Course I did provide this code from almost direct copy from System.Linq.Enumerable did not write myself other than the Func wrapper part.

2 Likes