Temelde yapmanız gereken bu - veya en azından en kolay çözüm bu. "Boşa harcayacağınız" tek şey n yöntem çağrısının maliyetidir - eğer düşünürseniz aslında herhangi bir vakayı iki kez kontrol etmeyeceksiniz. (IndexOf, eşleşmeyi bulur bulmaz geri dönecek ve kaldığı yerden devam edeceksiniz.)
Çerçeve yöntem (ler) inin biçimini taklit eden bir genişletme yöntemi olarak yinelemeli uygulama (yukarıdaki fikrin ):
public static int IndexOfNth(this string input,
string value, int startIndex, int nth)
{
if (nth < 1)
throw new NotSupportedException("Param 'nth' must be greater than 0!");
if (nth == 1)
return input.IndexOf(value, startIndex);
var idx = input.IndexOf(value, startIndex);
if (idx == -1)
return -1;
return input.IndexOfNth(value, idx + 1, --nth);
}
Ayrıca, size yardımcı olabilecek (doğru olduğunu kanıtlamak için) bazı (MBUnit) birim testleri şunlardır:
using System;
using MbUnit.Framework;
namespace IndexOfNthTest
{
[TestFixture]
public class Tests
{
//has 4 instances of the
private const string Input = "TestTest";
private const string Token = "Test";
/* Test for 0th index */
[Test]
public void TestZero()
{
Assert.Throws<NotSupportedException>(
() => Input.IndexOfNth(Token, 0, 0));
}
/* Test the two standard cases (1st and 2nd) */
[Test]
public void TestFirst()
{
Assert.AreEqual(0, Input.IndexOfNth("Test", 0, 1));
}
[Test]
public void TestSecond()
{
Assert.AreEqual(4, Input.IndexOfNth("Test", 0, 2));
}
/* Test the 'out of bounds' case */
[Test]
public void TestThird()
{
Assert.AreEqual(-1, Input.IndexOfNth("Test", 0, 3));
}
/* Test the offset case (in and out of bounds) */
[Test]
public void TestFirstWithOneOffset()
{
Assert.AreEqual(4, Input.IndexOfNth("Test", 4, 1));
}
[Test]
public void TestFirstWithTwoOffsets()
{
Assert.AreEqual(-1, Input.IndexOfNth("Test", 8, 1));
}
}
}