1
\$\begingroup\$

The title could probably be better, but in any case here goes.

I am having a bit of a problem understanding how to move methods/functions to other classes to organize things.

So, I have moved a method of sorts, but as I am skeptical of it, I would like to get it reviewed and hear opinions on what can be improved.

Here is the method ran from the default class:

private void GetAudioDevices()
{
    foreach (MMDevice device in Enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active))
    {
        comboBox1.Items.Add(device.FriendlyName);
        Console.WriteLine("{0}, {1}", device.FriendlyName, device.State);
    }
    PlayBackDevices = Enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active);
    for (waveInDevice = 0; waveInDevice < NAudio.Wave.WaveIn.DeviceCount; waveInDevice++)
    {
        DeviceInfo = WaveIn.GetCapabilities(waveInDevice);
        AudioDevices.Items.Add(DeviceInfo.ProductName);
    }
    if (AudioDevices.Items.Count > 0)
        AudioDevices.SelectedIndex = 0;

    AudioDevices.Items.Add("Wasapi Loopback");
    ListenAudioAgain = false;
    AudioDevice = AudioDevices.SelectedItem.ToString();
    comboBox1.SelectedItem = VoiceChatClass.Enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia).ToString();
}

Here it is when ran from a separate class:

public static void GetAudioDevices(ComboBox comboBox1, ComboBox AudioDevices)
{
    foreach (MMDevice device in VoiceChatClass.Enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active))
    {
        comboBox1.Items.Add(device.FriendlyName);
        Console.WriteLine("{0}, {1}", device.FriendlyName, device.State);
    }
    VoiceChatClass.PlayBackDevices = VoiceChatClass.Enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active);
    for (VoiceChatClass.waveInDevice = 0; VoiceChatClass.waveInDevice < NAudio.Wave.WaveIn.DeviceCount; VoiceChatClass.waveInDevice++)
    {
        VoiceChatClass.DeviceInfo = NAudio.Wave.WaveIn.GetCapabilities(VoiceChatClass.waveInDevice);
        AudioDevices.Items.Add(VoiceChatClass.DeviceInfo.ProductName);
    }
    if (AudioDevices.Items.Count > 0)
        AudioDevices.SelectedIndex = 0;

    AudioDevices.Items.Add("Wasapi Loopback");
    VoiceChatClass.ListenAudioAgain = false;
    VoiceChatClass.AudioDevice = AudioDevices.SelectedItem.ToString();
    comboBox1.SelectedItem = VoiceChatClass.Enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia).ToString();
        Console.WriteLine(VoiceChatClass.Enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia));
}

I am having difficulties understanding how to use static and non-static variables.

I just want to move it to a separate class for organization reasons. I know you can do it with partial classes, but sadly they are a bit "bugged" when used with a form in Visual Studio, as the design form will go away and stuff. It just gets unnecessarily complicated so to speak.

So anyway, what are your opinions upon viewing this? Is there a way to make it simpler? Are there any issues that have come up?

\$\endgroup\$
3
\$\begingroup\$

It seems to me like you are really asking about static vs non-static

  • static

This means that your instance or instance variable is class-bound. No matter how many objects you make, they will all share the same static variable. Take this class with a static variable called InstanceID. What it will do is increment the static variable by one for each object you create

public class StaticVSNonStatic
{
    private static int InstanceID = 0;

    public StaticVSNonStatic()
    {
        InstanceID++;
    }

    public int GetInstanceID() { return InstanceID; }
}

so say that you later create N number of StaticVSNonStatic objects it won't matter which one you call because they will all share the same variable and will output the same value.

StaticVSNonStatic s1 = new StaticVSNonStatic();
StaticVSNonStatic s2 = new StaticVSNonStatic();
StaticVSNonStatic s3 = new StaticVSNonStatic();

var value = s1.GetInstanceID(); // this will be 3

And if we create any more object of StaticVSNonStatic the InstanceID value will just keep on incrementing.

  • non-static

Simply means a variable or an object that is not declared as static. A variable that is not static is instance-bound, and for each instance you create they will have their own variable. So if we go back to the class above and remove the static keyword the value will always be 1 regardless of which object you are accessing and regardless of how many objects you have.

So anyway, what are your opinions upon viewing this? Is there a way to make it simpler? Are there any issues that have come up?

It seems like you do not quite understand how and when to create a class to represent an object and you don't fully understand static. But it's ok, OOP is a hard design pattern to grasp. Let's take a look of what you can improve and what makes me say that you don't understand it...

In a few places in your "seperate class" example you write

VoiceChatClass.ListenAudioAgain = false;
VoiceChatClass.AudioDevice = AudioDevices.SelectedItem.ToString();
VoiceChatClass.DeviceInfo =  Audio.Wave.WaveIn.GetCapabilities(VoiceChatClass.waveInDevice);
VoiceChatClass.PlayBackDevices = VoiceChatClass.Enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active);

Which are all static variables which you are invoking, but to me it looks like this should be non-static because to me it looks like you should be able to have multiple "unique" VoiceChat objects.

e.g., you should be able to have one VoiceChat object which has ListenAudioAgain set to false and another VoiceChat object which has it set to true. Or you could have two different VoiceChats with different PlayBackDevices. This is the way it should be but is impossible in your case because of the static.

. The first step in making sure we can have multiple "unique" VoiceChat objects is by removing the static keyword from the class, which should give you a class that looks something like this (remember that this is a guess since I can't actually know what the class looks like):

public class VoiceChat
{
    public bool ListenToAudioAgain { get; set; }
    public string AudioDevice { get; set; }
    public DeviceInfo DeviceInfo { get; set; }
    public PlayBackDevices[] PlayBackDevices { get; set; }
}

And you would use this (in your second example) by first creating (or passing it in by your parameters) an instance of the VoiceChat class. In this case we named the instance to voiceChat, and then we access its instance members.

public static void GetAudioDevices(ComboBox comboBox1, ComboBox AudioDevices)
{
    VoiceChat voiceChat = new VoiceChat()

    foreach (MMDevice device in voiceChat.Enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active))
    {
        comboBox1.Items.Add(device.FriendlyName);
        Console.WriteLine("{0}, {1}", device.FriendlyName, device.State);
    }

    voiceChat.PlayBackDevices = voiceChat.Enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active);

    for (voiceChat.waveInDevice = 0; voiceChat.waveInDevice < NAudio.Wave.WaveIn.DeviceCount; VoiceChatClass.waveInDevice++)
    {
        voiceChat.DeviceInfo = NAudio.Wave.WaveIn.GetCapabilities(VoiceChatClass.waveInDevice);
        AudioDevices.Items.Add(voiceChat.DeviceInfo.ProductName);
    }

    if (AudioDevices.Items.Count > 0) {
        AudioDevices.SelectedIndex = 0;
    }

    AudioDevices.Items.Add("Wasapi Loopback");

    voiceChat.ListenAudioAgain = false;
    voiceChat.AudioDevice = AudioDevices.SelectedItem.ToString();

    comboBox1.SelectedItem = voiceChat.Enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia).ToString();

    Console.WriteLine(voiceChat.Enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia));
}

This is a quick introduction so if there's something unclear just let me know and I'll try to clarify.

\$\endgroup\$
4
  • \$\begingroup\$ Okay after reading this i clearly see that i build my code completely different. I don´t even have Classes overall. I just have one huge class where i have Everything, which is why i want to separate it, but only because it´s so frustrating looking through the code as it´s so long. Which is why i asked about Static, as Static is very easy to make in other Classes, like a simple calculation and such, but i can´t use the Forms etc. Isn´t there a way to just "divide" the Class into separate classes, but everthing it sunder the same "Class"? (I know partial class works, but it´s a bit bugged. \$\endgroup\$ – Zerowalker Dec 18 '13 at 7:32
  • \$\begingroup\$ Oaky think i will go will Partial Classes anyway, it works as intended if you ignore the "bug". Will accept this answer, much can be learned from this thorough explanation, Much Thanks! \$\endgroup\$ – Zerowalker Dec 18 '13 at 7:46
  • \$\begingroup\$ @Zerowalker - Partial is also the wrong approach for your code :P You should spend a couple of hours trying to learn about OOP and classes. What "bug" is there when using partial classes with a form? \$\endgroup\$ – Max Dec 18 '13 at 7:51
  • \$\begingroup\$ Probably, but i think it´s much easier to have everything in 1 class, i think of it like 1 program or something. Luckily at my skills, it works good enough, but i guess a limit will be hit sooner or later. The "bug" is that if i make several Partial Classes of 1 class. And that main class is a form class, All will appear as Forms in Visual Studio, but all are New forms (empty window) and completely unnecessary, they don´t even show when starting the program as they aren´t even there. There is a why to bypass it by disabling the "form" to show, but that disabled the main form as well. \$\endgroup\$ – Zerowalker Dec 18 '13 at 11:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.