Shorter Syntax for Casting from a List<X> to a List<Y>

Shorter syntax for casting from a List X to a List Y ?

If X can really be cast to Y you should be able to use

List<Y> listOfY = listOfX.Cast<Y>().ToList();

Some things to be aware of (H/T to commenters!)

  • You must include using System.Linq; to get this extension method
  • This casts each item in the list - not the list itself. A new List<Y> will be created by the call to ToList().
  • This method does not support custom conversion operators. ( see Why does the Linq Cast<> helper not work with the implicit cast operator? )
  • This method does not work for an object that has an explicit operator method (framework 4.0)

Converting or casting List sting to List type in c#

Simply run through each element and create a new ClaimNumber object, populating the property.

With Linq:

// List<string> source = ...
List<ClaimNumber> claims = source.Select(s => new ClaimNumber { claimNumber = s }).ToList();

With a foreach

// List<string> source = ...
List<ClaimNumber> claims = new();
foreach (var s in source)
{
claims.Add(new ClaimNumber { claimNumber = s });
}

How to cast List object to List SomethingElse

LINQ, as implemented through the extension methods within the Enumerable class, relies on deferred execution:

Methods that are used in a query that returns a sequence of values do not consume the target data until the query object is enumerated. This is known as deferred execution.

Cast<T> does not create a new list immediately, but rather stores all the information that is required to perform the action. The list would only get enumerated when required (for example, through a foreach statement).

In your case, if you simply intend to iterate over the sequence, you should consider sticking to the IEnumerable<T> interface, which is the declared return type of Cast<T>:

IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();
foreach (SomethingElse se in second)
{
// ...
}

This is efficient, since it only performs the cast as each item is iterated.

If you’re convinced you want a new list to be created immediately, use ToList:

List<SomethingElse> second = first.Cast<SomethingElse>().ToList();

Edit: Replying to point posted in comment:

It depends on what you mean by “a list that can be modified”. There are several LINQ query operators that will allow you to alter the definition of your query further. For example, if you want to remove all SomethingElse elements whose IsDeleted property is true, you can use the Where operator:

IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();
second = second.Where(element => !element.IsDeleted);

If you want to add a sequence of new elements, you can use the Concat operator:

second = second.Concat(anotherCollectionOfSomethingElse);

If you want to sort your sequence in ascending order of ID, use the OrderBy operator:

second = second.OrderBy(element => element.ID);

Each time, we’re applying a query operator over the former definition of our query, and assigning the new (composite) query to our second variable. LINQ would store all your operators in the query definition. Then, when the sequence is actually enumerated (for example, through a foreach or ToList), it would give you the composite result of your sequence, with all the query operators applied in order.

As with all cases of deferred execution / lazy evaluation, be careful not to go overboard with this. If, for example, you’re going to apply a Where operator which will reduce the size of your sequence drastically, it might make sense to execute the query eagerly and store the enumerated list instead.

Casting List x to List y

Cast is used to change a non-generic collection into a generic one, i.e. it performs an unboxing operation. It can't be used the way you want.

When you have a look at the implementation of Cast and the CastIterator it uses, you see, that it takes an object and casts it to the specified type:

foreach (object current in source)
{
yield return (TResult)current;
}

This only works if current really is a TResult. No custom conversions are applied in this case.

This is the default behavior, you can test it yourself:

double d = 0.0;
object tmp = d;
int i = (int)tmp; // throws the same exception you are getting

What you want is best achieved with a simple Select if tblStocks is a generic enumerable:

List<JsonStock> stock = repository.Single(id).tblStocks
.Select(x => (JsonStock)x).ToList();

Or, if tblStocks is a non-generic enumerable, you need to combine Cast and Select:

List<JsonStock> stock = repository.Single(id).tblStocks.Cast<tblStock>()
.Select(x => (JsonStock)x).ToList();

This will first unbox the objects in tblStocks to their real type (tblStock) and then cast it to the type you want (JsonStocks).

Casting from double to short decreasing the result in C

Given the constraints on a, b, and c, we can compute the desired result as (short) (a * lround(10*b) / lround(10*c)) or as (short) (a * b / c + .00005). (This of course requires that the result be representable in short. That is not guaranteed by the stated limits on a, b, and c.)

In the former, ab/c is equivalent to a•10b/(10c), so we just need to show this is what the expression computes, including that the arithmetic does not suffer from rounding errors. We know b would ideally be a multiple of .1, so 10*b would be an integer. lround(10*b) finds this integer, effectively correcting for any error that occurred in converting a decimal numeral to the double format. Similarly, lround(10*c) finds the ideal value of 10*c. lround returns a value in the long type, so the multiplication and the division are performed with integer arithmetic. Also, the long type is capable of representing the necessary range. (a * lround(10*b) is limited to 3,650,000, and long can represent up to at least 2,147,483,647.) So the multiplication is exact, the division truncates the way we desire.

A proof for the latter follows.

The following assumes the IEEE-754 “double” format is used for double. It is sufficient that, after <float.h> is included, #if DBL_MANT_DIG >= 53 is true.

Conversion of a numeral in a user-provided string to double ought to yield a number with error of at most one unit of least precision (ULP). This is suggested in various places in the C standard (and it is unclear whether certain parts of the text intend to require this). However, let’s assume we have a bad conversion with error up to 1024 ULP.

b and c can be up to 1000, for which the ULP is 2−43, so 1024 ULP is 2−33. Thus, if the user enters b, b is b(1+eb), where |eb| ≤ 2−33, and c is similarly c(1+ec). As an integer up to 365, a is of course exactly the a entered by the user.

When a * b is computed, the result is
ab(1+eb)(1+e0), where e0 is the error introduced by the multiplication. In any rounding mode, |e0| is less than 1 ULP. The maximum value at this point is 365,000, for which 1 ULP is 2−34.

Then we divide by c, for which the minimum value is 1. The result is
ab(1+eb)(1+e0)/(c(1+ec))•(1+e1), where e1 is the error introduced the division. Again the maximum value is 365,000, so |e1| < 2−34.

Rearranging, the result is ab/c • (1+eb)(1+e0)(1+e1)/(1+ec). We can easily see a bound for the error is given when eb is +2−33, e0 and e1 are 2−34, and ec is −2−33. Some work with a calculator shows us the error is less than 3.5•10−10.

Note that ab/c equals 10ab/(10c) and consider the latter. The numerator is an integer, and the denominator is an integer that is at most 10,000. Therefore, the closest the quotient can be to an integer without being an integer is .0001. And the closest the result computed with rounding errors can be to an integer is less than .0001 − 3.5•10−10. Therefore, if we add .00005 to the computed result, it will push every result that would have been an integer (without rounding errors) above that integer but it will not push any result that would not have been an integer above the next integer. Therefore, the integer below a * b / c + .00005 is the desired result, and casting to short provides that integer, if it is it range of short.



Related Topics



Leave a reply



Submit