From: Mel Weaver on
Try this, just a reminder c# is case sensitive?



using System.Collections.Generic;

public static class EnumerableExtensions
{
private static readonly Random random = new Random();

public static IEnumerable<T> selectrandomitem<T>(this IEnumerable<T>
source, int total)
{
if (source == null) yield break;

T[] data = source.ToArray();

if (total < 0 || total > data.Length)
{
throw new ArgumentException();
}

for (int i = 0; i < total; i++)
{
int index = random.Next(data.Length - i);
yield return data[index];
data[index] = data[data.Length - i - 1];
}
}
}


"Rich P" <rpng123(a)aol.com> wrote in message
news:OXm3jsXDLHA.4400(a)TK2MSFTNGP05.phx.gbl...
> Thank you for your reply. This did fix one of the complaints from
> VS2008, but he is still complaining about one other guy. Here is the
> sample class that I copied from another post with the recommended fix of
> adding <T> to ...class EnumerableExtensions :
>
> public static class EnumerableExtensions<T>
> {
> private static readonly Random random = new Random();
>
> //--VS2008 is complaining about "selecttrandomitem<t>"
>
> public static ienumerable<t> selectrandomitem<t>(this ienumerable<t>
> source, int total)
> {
> if (source == null) yield break;
>
> T[] data = source.ToArray();
>
> if (total < 0 || total > data.Length)
> {
> throw new ArgumentException();
> }
>
> for (int i = 0; i < total; i++)
> {
> int index = random.Next(data.Length - i);
>
> yield return data[index];
>
> data[index] = data[data.Length - i - 1];
> }
> }
> }
>
> Here is the error message for "selecttrandomitem<t>"
>
> "The body of
> 'MySampleApp.EnumerableExtensions<T>.selectrandomitem<t>(ienumerable<t>,
> int)' cannot be an iterator block because 'ienumerable<t>' is not an
> iterator interface type"
>
> This sample class is great for learning Generics in C#. May I ask how I
> could fix this error based on the context of the sample above?
>
> Thanks
>
> Rich
>
> *** Sent via Developersdex http://www.developersdex.com ***

From: Rich P on
OK. Now I have this class -- which VS is not complaining about. How to
I use a class like this? Could someone share a sample usage?

public static class enumerableextensions<t>
{
private static readonly Random random = new Random();

public static IEnumerable<t> selectrandomitem<t>(this IEnumerable<t>
source, int total)
{
if (source == null) yield break;

t[] data = source.ToArray();

if (total < 0 || total > data.Length)
{
throw new ArgumentException();
}

for (int i = 0; i < total; i++)
{
int index = random.Next(data.Length - i);

yield return data[index];

data[index] = data[data.Length - i - 1];
}
}
}

In the post I copied this from -- VS complains about the following usage
and I don't see a connection to the class above:

static void Main(string[] args)
{
var data = Enumerable.Range(0, 21);

//--VS complains here about "SelectRandomItem"
foreach (var item in data.SelectRandomItem(10))
{
Console.WriteLine(item);
}
}

I tried changing the casing of "SelectRandomItem", VS still complain,
and still I don't see the connection to the class above. The post was
about picking 10 numbers randomly from a list of numbers. I just copied
this post to study usage of Generics.


Rich

*** Sent via Developersdex http://www.developersdex.com ***
From: kndg on
On 6/17/2010 3:05 AM, Rich P wrote:
> OK. Now I have this class -- which VS is not complaining about. How to
> I use a class like this? Could someone share a sample usage?
>
> public static class enumerableextensions<t>
> {
> private static readonly Random random = new Random();
>
> public static IEnumerable<t> selectrandomitem<t>(this IEnumerable<t>
> source, int total)
> {
> if (source == null) yield break;
>
> t[] data = source.ToArray();
>
> if (total< 0 || total> data.Length)
> {
> throw new ArgumentException();
> }
>
> for (int i = 0; i< total; i++)
> {
> int index = random.Next(data.Length - i);
>
> yield return data[index];
>
> data[index] = data[data.Length - i - 1];
> }
> }
> }
>
> In the post I copied this from -- VS complains about the following usage
> and I don't see a connection to the class above:
>
> static void Main(string[] args)
> {
> var data = Enumerable.Range(0, 21);
>
> //--VS complains here about "SelectRandomItem"
> foreach (var item in data.SelectRandomItem(10))
> {
> Console.WriteLine(item);
> }
> }
>
> I tried changing the casing of "SelectRandomItem", VS still complain,
> and still I don't see the connection to the class above. The post was
> about picking 10 numbers randomly from a list of numbers. I just copied
> this post to study usage of Generics.
>
>
> Rich
>
> *** Sent via Developersdex http://www.developersdex.com ***

Hi Rich,

I glad that you benefit something from my code.
Anyway, as for the comments, if you copy my code exactly as it appear,
it should compile fine.
- SelectRandomItem is an extension method and it can only be declared on
a *non-generic* static class. You had mistakenly make the class generic
by adding <t> on the class definition. That's the source of error.
- It is a well known practice to use upper-case letter 'T' as a
placeholder for the generic type. Otherwise, it will upset your collegues.
- You need to work up on proper casing of names.

As for the usage, if you follow my example carefully, it will print 10
random numbers in the range of 0 to 20. Another usage is for example
suppose you would like to calculate the sum of three dices thrown on the
table,

static void Main(string[] args)
{
var dice = Enumerable.Range(1, 6);

var threeDices = new List<int>(dice); // first dice
threeDices.AddRange(dice); // second dice
threeDices.AddRange(dice); // third dice

int sumOfThreeDices = threeDices.SelectRandomItem(3).Sum();

Console.WriteLine("Sum of three dice = {0}", sumOfThreeDices);
}

Regards.
From: Rich P on
>
SelectRandomItem is an extension method and it can only be declared on a
*non-generic* static class. You had mistakenly make the class generic by
adding <t> on the class definition. That's the source of error.
<

Thank you for your reply. I still get an error if I copy your class
like this:

public static class EnumerableExtensions
{
private static readonly Random random = new Random();

//--VS complains here about selectrandomitem
public static ienumerable<t> selectrandomitem<t>(this ienumerable<t>
source, int total)
{
if (source == null) yield break;

//--VS complains about T[]
T[] data = source.ToArray();

if (total < 0 || total > data.Length)
{
throw new ArgumentException();
}

for (int i = 0; i < total; i++)
{
int index = random.Next(data.Length - i);
//--and VS complains about data[index]
yield return data[index];
data[index] = data[data.Length - i - 1];
}
}
}

Here are the error messages I am getting with this class (VS2008)

--error1
The body of
'ConsoleApplication1.EnumerableExtensions.selectrandomitem<t>(ienumerabl
e<t>, int)' cannot be an iterator block because 'ienumerable<t>' is not
an iterator interface type

--error2
The type or namespace name 'T' could not be found (are you missing a
using directive or an assembly reference?)

--error3
Cannot implicitly convert type 'T' to 'object'

What should I do to eliminate these errors?

Also, not sure if this is of any significance, but I also see that a lot
of code sampels have

* list<something> x = new list<something>() *

on my workstation I don't have a * list *. I have to use uppercase *
List *. Is my VS2008 different? I am pretty sure I have all the latest
patches for it and service packs (version 3.5 SP1).

Thanks,



Rich

*** Sent via Developersdex http://www.developersdex.com ***
From: kndg on
On 6/17/2010 11:36 PM, Rich P wrote:
>>
> SelectRandomItem is an extension method and it can only be declared on a
> *non-generic* static class. You had mistakenly make the class generic by
> adding<t> on the class definition. That's the source of error.
> <
>
> Thank you for your reply. I still get an error if I copy your class
> like this:
>
> public static class EnumerableExtensions
> {
> private static readonly Random random = new Random();
>
> //--VS complains here about selectrandomitem
> public static ienumerable<t> selectrandomitem<t>(this ienumerable<t>
> source, int total)
> {
> if (source == null) yield break;
>
> //--VS complains about T[]
> T[] data = source.ToArray();
>
> if (total< 0 || total> data.Length)
> {
> throw new ArgumentException();
> }
>
> for (int i = 0; i< total; i++)
> {
> int index = random.Next(data.Length - i);
> //--and VS complains about data[index]
> yield return data[index];
> data[index] = data[data.Length - i - 1];
> }
> }
> }
>

As I said previously, If you had copy the code exactly as it appear, it
should compile fine. You had mistakenly changed the casing for
IEnumerable<T> and SelectRandomItem<T> and that cause the compiler to
complaint.

> Here are the error messages I am getting with this class (VS2008)
>
> --error1
> The body of
> 'ConsoleApplication1.EnumerableExtensions.selectrandomitem<t>(ienumerabl
> e<t>, int)' cannot be an iterator block because 'ienumerable<t>' is not
> an iterator interface type
>

As others has said, C# is *case-sensitive*. There is no ienumerable<t>
in the framework, only IEnumerable<T> which is defined in
System.Collections.Generic namespace. Since I had use 'yield break' and
'yield return' statement in the method block, the return type of the
SelectRandomItem method must be of type IEnumerable<T>.

> --error2
> The type or namespace name 'T' could not be found (are you missing a
> using directive or an assembly reference?)
>

I had made the SelectRandomItem method generic by adding <T> at the name
of methods. You had mistakenly changed the casing from uppercase <T> to
lowercase <t>. Generic type declaration have to be consistent with the
usage inside the method. If you use lowercase 't' on the method
definition, you must also use the same lowercase 't' inside the method body.

> --error3
> Cannot implicitly convert type 'T' to 'object'
>

If you resolve the error2 above, this error should go away.

> What should I do to eliminate these errors?
>

Well, read the code carefully and work up on the proper casing.

> Also, not sure if this is of any significance, but I also see that a lot
> of code sampels have
>
> * list<something> x = new list<something>() *
>
> on my workstation I don't have a * list *. I have to use uppercase *
> List *. Is my VS2008 different? I am pretty sure I have all the latest
> patches for it and service packs (version 3.5 SP1).
>

Care to share where do you get that code sample? Maybe a typing error or
maybe the author of that code did defined a new type named list<T>?
Without the original code, I cannot say for sure but as far as .NET is
concerned, all classes name in the framework starts with the uppercase
letter.

In order to aid your understanding of my code, below are the features
that I had used and the links to MSDN website for the details

1. Generics
http://msdn.microsoft.com/en-us/library/512aeb7t%28VS.90%29.aspx

2. Iterators
http://msdn.microsoft.com/en-us/library/dscyy5s0%28VS.90%29.aspx

3. Extension Methods
http://msdn.microsoft.com/en-us/library/bb383977%28VS.90%29.aspx


Regards.