1

I tried to build a test app using this code example

I define a public class as per below:

 public class iSpeech
 {
    // Performs synthesis
    public async Task<IRandomAccessStream> SynthesizeTextToSpeechAsync(string text)
    {
        IRandomAccessStream stream = null;
        using (SpeechSynthesizer synthesizer = new SpeechSynthesizer())
        {
            VoiceInformation voiceInfo =
              (
                from voice in SpeechSynthesizer.AllVoices
                where voice.Gender == VoiceGender.Male
                select voice
              ).FirstOrDefault() ?? SpeechSynthesizer.DefaultVoice;

            synthesizer.Voice = voiceInfo;
            stream = await synthesizer.SynthesizeTextToStreamAsync(text);
        }
        return (stream);
    }

    // Build audio stream
    public async Task SpeakTextAsync(string text, MediaElement mediaElement)
    {
        IRandomAccessStream stream = await this.SynthesizeTextToSpeechAsync(text);
        await mediaElement.PlayStreamAsync(stream, true);
    }
}

From the application main page, I then tried to call as:

    public async void btnClick(object sender, RoutedEventArgs e)
    {
        await iSpeech.SpeakTextAsync("test speech", this.uiMediaElement);
    }

I keep on getting

"an object reference is required for the non-static field, method, or Property..." error.

Could someone please let me know what I am doing incorrectly?

Mohamed
  • 806
  • 13
  • 30
Franck E
  • 629
  • 8
  • 26

2 Answers2

5

iSpeech is a class, but you need an instance of the class in order to use non-static methods.

Think of it like List<string>. You can't call

List<string>.Add("Hello"); 

because List<string> is a class, like the blueprint for creating an object. (You would get the exact same error.) You would need to create an instance of that class to use it:

var myList = new List<string>();
myList.Add("Hello");

So in the case of your class, iSpeech, if you declared

var mySpeechThing = new iSpeech();

then mySpeechThing would be a variable representing an instance of iSpeech, and then you could do

await mySpeechThing.SpeakTextAsync("test speech", this.uiMediaElement);

Sometimes a class has methods that can be called without modifying the state of the object (like calling Add on a List<string> changes its state by adding a string to it.) We declare those as static methods. They belong to the class, not to an instance of the class.

To do that you would put the keyword static in the method declaration like this:

public static async Task SpeakTextAsync(string text, MediaElement mediaElement)

Then you could use it the way you were trying to.

static methods cannot access non-static class properties or methods. And although some may disagree, it's generally better practice not to use static methods. They're not evil, but until you're more familiar I'd lean the other way.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
  • Many thanks Scott, this is exactly what I needed. var mySpeechThing = new iSpeech(); await mySpeechThing.SpeakTextAsync("test speech", this.uiMediaElement); – Franck E Jul 16 '16 at 02:19
  • You're welcome! Hair-splitting detail: to make code more consistently readable it's recommended to make classes start with upper case letters. And unless it's a word that starts with "I", prefacing a type name with "I" is usually used for interfaces. (But there are obviously no rules.) – Scott Hannen Jul 16 '16 at 02:33
1

You are missing the "static" keyword in the Method SpeakTextAsync.

public static async Task SpeakTextAsync(string text, MediaElement mediaElement)
{
    IRandomAccessStream stream = await this.SynthesizeTextToSpeechAsync(text);
    await mediaElement.PlayStreamAsync(stream, true);
}
Allan F. Gagnon
  • 320
  • 2
  • 7
  • Thanks for your reply Alan. Unfortunately, this.SynthesizeTextToSpeechAsync cannot be static and return error. The next reply solved it. – Franck E Jul 16 '16 at 02:18