Нет простой встроенной строковой функции, которая делает то, что вы ищете, но вы можете использовать более мощные регулярные выражения :
import re
[m.start() for m in re.finditer('test', 'test test test test')]
#[0, 5, 10, 15]
Если вы хотите найти совпадающие совпадения, lookahead будет делать это:
[m.start() for m in re.finditer('(?=tt)', 'ttt')]
#[0, 1]
Если вы хотите иметь обратную find-all без перекрытий, вы можете комбинировать положительный и отрицательный lookahead в выражении типа это:
search = 'tt'
[m.start() for m in re.finditer('(?=%s)(?!.{1,%d}%s)' % (search, len(search)-1, search), 'ttt')]
#[1]
re.finditer
возвращает генератор , поэтому вы можете изменить []
выше, на ()
, чтобы получить генератор вместо списка, который будет более эффективен, если вы только итерации через результаты один раз.
C.Connect()
не вызывается, и это необходимо, поскольку именно здесь вы регистрируете EventHandler, который вызывает this.sender_PageSwap
. Без этого ничего не произойдет.
Как работают события и проблема с вашим кодом
blockquote>События - это оболочка поверх Delegate, которая обеспечивает безопасный тип доступа, без возможности повредить делегировать состояние объекта. В вашем случае
class A
инициирует регистрацию события посредством вызова методаOnPageSwap
, определенного в классе B, который в первую очередь должен вызвать методConnect
в классе C, который выполняет регистрацию событияPageSwap
и должен использовать тот же экземпляр объекта B, который используется для вызова метода Connect, так что регистрация событий может быть подключена и, таким образом, вызвана,new object B
не требуется вClass C
. Экземпляр может быть передан в методе или в конструкторе. Мой пример кода делает это в методеConnect(B sender)
Простыми словами
blockquote>Вы не вызываете метод
Connect
в [ 1110], а затем регистрация события внутриConnect method
должна быть тем же объектом изClass B
. Также дизайн события некорректен, так как он не является потокобезопасным и объект может быть поврежден. Событие должно быть выставлено через аксессор.Ниже приводится рабочая версия кода, включая тестовую консоль
blockquote>void Main() { new A().Button_Click(this, new RoutedEventArgs()); } public class A { public void Button_Click(object sender, RoutedEventArgs startEventArgs) { B senders = new B(); senders.OnPageSwap(new StartEventArgs()); } } public delegate void StartEventHandler(object sender, StartEventArgs e); public class B { private event StartEventHandler _PageSwap; private readonly object _lock = new Object(); // Event Access via thread safe accessor public event StartEventHandler PageSwap { add { lock (_lock) { _PageSwap += value; } } remove { lock (_lock) { _PageSwap -= value; } } } public virtual void OnPageSwap(StartEventArgs e) { Console.WriteLine("Entered PageSwapSender"); var c = new C(); c.Connect(this); if (_PageSwap != null) _PageSwap(this, e); } } public class C { public void Connect(B sender) { sender.PageSwap += new StartEventHandler(this.sender_PageSwap); Console.WriteLine("Entered Connect"); } private void sender_PageSwap(object sender, StartEventArgs e) { Console.WriteLine("Entered Handler"); } } public class StartEventArgs : EventArgs { }
Изменения: [ 1127] blockquote>
- Изменено определение метода Connect на
public void Connect(B sender)
, так чтоclass C
получает тот же объект класса B, который вызывает метод Connect внутриpublic virtual void OnPageSwap(StartEventArgs e)
изClass B
]- Создано
StartEventArgs
в качестве заполнителя, который может быть заменен реальным кодом- Предоставлена тестовая консоль для проверки вызова рабочего процесса / события
[1128 ] Результат:blockquote>
Entered PageSwapSender Entered Connect Entered Handler
Редактировать 1:
blockquote>Рядом с неверным доступом для событие, в котором не используется тот же объект, дизайн события имеет недостатки, его необходимо предоставлять через потоковый метод доступа, рассмотрим последнюю модификацию кода, где событие PageSwap предоставляется через потоковую оболочку
Проблема с вашим кодом в том, что вы создаете два отдельных экземпляра класса B
. В A
вы пытаетесь вызвать событие в одном случае B
. В C
вы пытаетесь обработать событие, вызванное , используя экземпляр разности B
.
Кажется, что вы пытались сделать правильную вещь, создав метод Connect
в C
, но именно здесь вы должны передать существующий экземпляр B
до C
[ 1114].
Если бы вы написали свой код так, он бы работал:
class A
{
public void Button_Click(object sender, RoutedEventArgs e)
{
B senders = new B();
C c = new C();
c.Connect(senders);
senders.OnPageSwap(new StartEventArgs());
}
}
public delegate void StartEventHandler(object sender, StartEventArgs e);
public class B
{
public event StartEventHandler PageSwap;
public virtual void OnPageSwap(StartEventArgs e)
{
Console.WriteLine("Entered PageSwapSender");
if (PageSwap != null) PageSwap(this, e);
}
}
class C
{
public void Connect(B sender)
{
sender.PageSwap += new StartEventHandler(this.sender_PageSwap);
Console.WriteLine("Entered Connect");
}
private void sender_PageSwap(object sender, StartEventArgs e)
{
Console.WriteLine("Entered Handler");
}
}