Reputation: 19933
Back from interview. I share with you and a good and precise answer is welcome.
The purpose, you have a static method, this method receive an IList<int>
you have
to get back the values you can divise by 3 and make the code.
Constraint : The original list (in the main) has a reference on the stack and the values on the heap, the result must be return (it's a void method) in the same space (on the heap) than the original list. The solution show here is not correct because in the method a new pointer on the stack + heap are created in the method domain. Solution ?
Bonus : how change the code to receive not only int but float, double, ....
static void Main(string[] args)
{
IList<int> list = new List<int>() { 9, 3, 10, 6, 14, 16, 20};
CanBeDivedByThree(list);
}
static void CanBeDivedByThree(IList<int> list)
{
list = (from p in list
where p % 3 == 0
orderby p descending
select p).ToList<int>();
}
Upvotes: 4
Views: 1082
Reputation: 176259
That's meaningless as the internal storage to an IList
is not under your control. Adding (or possibly removing) items might re-allocate the internal data structures.
It is especially meaningless as the list in your sample contains value types which are copied anyway when you access them.
Last but not least it's basically the whole point of using a managed language that you don't have to worry about memory (al)locations. Such things are implementation details of the platform.
To take up on your bonus question: There is no simple way to achieve that. One could think that using generics with a type constraint would solve the problem here (something like static void CanBeDivedByThree<T>(IList<T> list) where T : struct
), but the problem is that C# does not (yet?) have support for generic arithmetic. C# doesn't have a modulo operator that can take a generic parameter of type 'T' and 'int'.
Upvotes: 9
Reputation: 108880
Unfortunately only List but not IList does implement RemoveAll. So I first implement it as an extension method.
public static int RemoveAll<T>(this IList<T> list, Predicate<T> match)
{
if (match == null)
throw new ArgumentNullException("match");
int destIndex=0;
int srcIndex;
for(srcIndex=0;srcIndex<list.Count;srcIndex++)
{
if(!match(list[srcIndex]))
{
//if(srcIndex!=destIndex)//Small optimization, can be left out
list[destIndex]=list[srcIndex];
destIndex++;
}
}
for(int removeIndex=list.Count-1;removeIndex>=destIndex;removeIndex--)
{
list.RemoveAt(removeIndex);
}
return srcIndex-destIndex;
}
Then you can use:
list.RemoveAll(n => n % 3 != 0);
You can then use overloads for other types. Unfortunately you can't (easily) make it generic since generics don't work with operator overloading.
Upvotes: 2
Reputation: 1503469
Others have covered the list part - this is just for the bonus bit.
You can't do this in a statically typed way using C# generics, but if you're using C# 4 you can do it with dynamic typing. For example:
using System;
using System.Collections.Generic;
class Test
{
static void Main()
{
ShowDivisibleBy3(new List<int> { 1, 3, 6, 7, 9 });
ShowDivisibleBy3(new List<decimal> { 1.5m, 3.3m, 6.0m, 7m, 9.00m });
}
static void ShowDivisibleBy3<T>(IEnumerable<T> source)
{
foreach (dynamic item in source)
{
if (item % 3 == 0)
{
Console.WriteLine(item);
}
}
}
}
Upvotes: 1
Reputation: 35594
list.RemoveAll(n => n % 3 == 0);
or
for (int i = list.Count - 1; i >= 0; --i)
{
if (list[i] % 3 != 0)
list.RemoveAt(i);
}
The first approach works only for List<T>
.
One could make it a template method, but remainder operation doesn't make much sense on floats.
Upvotes: 2