There is not much to add to the other answers. Your code is well written and easy to understand, but as a brute force algorithm it has its limitation in real world use - for larger data sets at least.
The name should be MaxPairProduct (PascalCase) instead of maxPairProduct.
There is maybe an issue (that applies to the other answers as well):
For the dataset:
int[] data = { 1, 2, 3 }
it returns 3, but it should return -1, if the multiplier and, multiplicand and product must be different fromdistinct entries in the product itselfdata set? The dataset { 1, 2, 3, 3 } should return 3.
Similar
int[] data = { 1, 2, 2, 3, 4, 5 };
should return 4 but returns 5.
The above is somehow inconsistent with:
int[] data = { 2, 3, 4 };
that correctly results in -1.
Below is an implementation that handles the above problem, and also prevent a possible overflow when multiplying:
static int MaxPairProduct(int[] a)
{
Array.Sort(a);
int product;product = -1;
int multiplier;multiplier = -1;
int multiplicand;
for (int i = a.Length - 1; i > 1; --i)
{
if (a[i] == product) continue;
product = a[i];
for (int j = 0; j < i; ++j)
{
if (a[j] == multiplier) continue;
multiplier = a[j];
if (multiplier == 0) continue;
multiplicand = product / multiplier;
if (product % multiplier == 0 && Array.IndexOf(a, multiplicand, j + 1, i - j - 1) > j)
{
return product;
}
if (multiplicand < multiplier)
break;
}
}
return -1;
}