2012-06-07 3 views
0

У меня есть следующая структуратаймера как часть структуры

private struct sData{ 
    public int volume;  
    public System.Timers.Timer aliveTimer; 
    public void OnTimedEvent(object source, ElapsedEventArgs e) 
    { 
     Console.WriteLine("this = " + volume);// I cannot access volume here 
    } 
} 

и когда время, прошедшее с началом я хочу, чтобы изменить значение громкости и я не могу получить доступ к нему в OnTimedEvent Я использую этот код, чтобы начать-структуру и таймер:

sData ret = new sData(); 
ret.volume = rand.Next(1, 10) * 100;  
ret.aliveTimer = new System.Timers.Timer(1000); 
ret.aliveTimer.Elapsed += new ElapsedEventHandler(sData.OnTimedEvent); 
ret.aliveTimer.Start(); 

Что мне делать?

+2

Что такое ошибка, которую вы получаете? Кроме того, зачем использовать struct, а не класс? – RvdK

+1

Изменить его как «класс»? В любом случае, беспорядочные 'struct' редко бывают хорошей идеей. Почему вы создали его как 'struct'? –

+1

События на 'struct' обычно являются плохим шагом. Почему это «структура»?Если вы не можете четко ответить **, почему это «структура», то это почти наверняка не должно быть одним. И * изменяемая * 'struct' с открытым полем - это просто * попрошайничество * для проблем. –

ответ

1

Я бы переписать его:

private class Data{ 
    public int Volume {get; set; }  
    private System.Timers.Timer _aliveTimer; 

    public Data() 
    { 
     _aliveTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent); 
    } 

    public void Start() 
    { 
     _aliveTimer.Start(); 
    } 

    private void OnTimedEvent(object source, ElapsedEventArgs e) 
    { 
     Console.WriteLine("this = " + volume); 
    } 
} 

Data ret = new Data(); 
ret.Volume = rand.Next(1, 10) * 100;  
ret.Start(); 

Использование класса всегда лучшая идея, чем структуры. Данные Furthurmore содержат таймер, но вы устанавливаете обработчик OnTimedEvent (который определен в Data) из другого компонента. Бит нелогичен.

+0

незначительная настройка - я бы сделал 'Volume' авто-prop; публичные поля никогда не являются хорошей идеей. Неясно, как '_aliveTimer' когда-нибудь получит ненулевое значение здесь или как оно будет очищено. –

2

k; Теперь я понимаю сообщение об ошибке. В вашем примере кода, у вас есть:

ret.aliveTimer.Elapsed += new ElapsedEventHandler(sData.OnTimedEvent); 

, который предполагает, что в вашем реального кода, OnTimedEvent является static - что объясняет, почему вы получаете сообщение (комментарии):

ссылка на объект требуется для нестатического поля, метода или свойства «TimerTester.Form1.sData.volume

So; первоначальная проблема заключается в том, что OnTimedEvent не должен быть static. Это, в свою очередь, означает, что подписка на события будет:

ret.aliveTimer.Elapsed += new ElapsedEventHandler(ret.OnTimedEvent); 

или просто:

ret.aliveTimer.Elapsed += ret.OnTimedEvent; 

Однако! Подписки от подписки на структуры ... рискованны. Семантика копий структур делает практически невозможным их правильное использование в качестве источников событий или подписчиков. sDataясно не «значение», поэтому просто не должно быть struct: оно должно быть class. Если вы когда-либо сомневаетесь, class охватывает 99,99% сценариев. struct является очень редко, и еще реже при использовании правильно, а не кого-то, кто думает, что struct средства «как class, но дешевле» (это не то, что это значит).

Я также хотел бы изменить многие черты sData (в том числе имени, использование общественных полей, открытые детали реализации, и т.д.) - но это вторично по отношению к двум большим проблем:

  • путаницы в использовании из struct
  • путаницы в использовании static
Смежные вопросы