locked
IEnumerable Question RRS feed

  • Question


  • Is this possible? trying to split a string out of a value and then back into a IEnumerable.......

    I am splitting this out and returning it as separate rows The delim is \r\n:
    {[Report Criteria, Filter Criteria
     :.Archived
     :  :.All
     :.Request ID
     :  :.xxx
     :.Group & Sort Criteria
        :.Employee Name Ascending
        :.Agency Org Ascending
    Report Executed on : xxxxxxxxxxxxxxxxxx UTC]}



    Here is the code: I am going to replace rx with rx1, but rx1 does not have "rx1.MoveNext" look below
                    var rx = ((IEnumerable)e.Current).GetEnumerator();
                    IEnumerable enumerable;
                    var rx1 = (IEnumerable)rebuildReportCriteria(((IEnumerable)e.Current).GetEnumerator());


                    for (int j = 0; rx1.MoveNext(); j++)
                    {
                        object v = ((KeyValuePair<string, object>)rx.Current).Value;
                        string s = "", l = "";...................................



            private static object rebuildReportCriteria(IEnumerator enumerator)
            {
                var list = new List<KeyValuePair<string, string>>();
                string v = "";
                for (int j = 0; enumerator.MoveNext(); j++)
                {
                    v = ((KeyValuePair<string, object>)enumerator.Current).Key;
                    if (v == "Report Criteria")
                    {
                        string[] stringSeparators = new string[] { "\r\n" };
                        string[] lines = ((KeyValuePair<string, object>)enumerator.Current).Value.ToString().Split(stringSeparators, StringSplitOptions.None);

                        foreach (string s in lines)
                        {
                            list.Add(new KeyValuePair<string, string>(((KeyValuePair<string, object>)enumerator.Current).Key, ((KeyValuePair<string, object>)enumerator.Current).Value.ToString()));
                        }
                    }
                }
                if (v == "Report Criteria")
                {
                    return list.GetEnumerator();
                }
                else
                {
                    return enumerator;
                }
            }

    www.helixpoint.com

    Friday, March 4, 2016 4:39 PM

Answers

  • You really shouldn't be using MoveNext directly but it is defined. I'm really trying to understand what you're code is doing but it doesn't look like all the pieces are there.  Ultimately I believe the issue with your code is that you're trying to convert Split results to something it isn't.

    Specifically you are using 1.x objects rather than the generic versions so your code is doing a lot of casting and whatnot that is both unsafe and harder to read.  I'm also not clear what you are actually passing to your rebuildReportCriteria method. That is going to determine what you can do. You are also trying to return IEnumerator which is something you pretty much never do outside an actual collection implementation.  Finally I notice that your method does a lot of work but unless a specific case is true then you don't actually do anything with the results.  So knowing how the results of this method call are being used would help clarify what you need as well.

    I'm going to take a crack at trying to accomplish what you want but I'm making lots of assumptions here.

    //TODO: If this is actually a dictionary, then use that instead of IEnumerable<KeyValuePair> but the code breaking up 
    //the lines won't work work correctly if you're using the same key
    private static IEnumerable<KeyValuePair<string, string>> rebuildReportCriteria ( IEnumerable<KeyValuePair<string, string>> source )
    {
        //TODO: This code seems to be looking for a specific item so don't bother to enumerate
        var criteria = source.FirstOrDefault(i => i.Key == "Report Criteria");
        if (String.IsNullOrEmpty(criteria.Key))
            return source;
    
        var lines = criteria.Value.Split(new [] { "\r\n" }, StringSplitOptions.None);
    
        //TODO: The existing code didn't look correct at all.  It was getting the current key and the type of the value and adding them to the list
        //for each line but doing nothing with the lines.
        return from line in lines
                select new KeyValuePair<string, string>(criteria.Key, line);
    }

    • Proposed as answer by Kristin Xie Tuesday, March 15, 2016 1:55 AM
    • Marked as answer by Kristin Xie Tuesday, March 15, 2016 2:06 AM
    Friday, March 4, 2016 6:04 PM

All replies

  • Does String.Split not do what you want?  It returns an array where the string is split by the given delimiter.  An array is IEnumerable so you get what you want.

    Michael Taylor
    http://www.michaeltaylorp3.net

    Friday, March 4, 2016 4:56 PM
  • It returns just fine, but I get:

    rx1.MoveNext(); j++)

    give me:

    IEnumerable does not have a definition for movenext


    www.helixpoint.com

    Friday, March 4, 2016 5:26 PM
  • You really shouldn't be using MoveNext directly but it is defined. I'm really trying to understand what you're code is doing but it doesn't look like all the pieces are there.  Ultimately I believe the issue with your code is that you're trying to convert Split results to something it isn't.

    Specifically you are using 1.x objects rather than the generic versions so your code is doing a lot of casting and whatnot that is both unsafe and harder to read.  I'm also not clear what you are actually passing to your rebuildReportCriteria method. That is going to determine what you can do. You are also trying to return IEnumerator which is something you pretty much never do outside an actual collection implementation.  Finally I notice that your method does a lot of work but unless a specific case is true then you don't actually do anything with the results.  So knowing how the results of this method call are being used would help clarify what you need as well.

    I'm going to take a crack at trying to accomplish what you want but I'm making lots of assumptions here.

    //TODO: If this is actually a dictionary, then use that instead of IEnumerable<KeyValuePair> but the code breaking up 
    //the lines won't work work correctly if you're using the same key
    private static IEnumerable<KeyValuePair<string, string>> rebuildReportCriteria ( IEnumerable<KeyValuePair<string, string>> source )
    {
        //TODO: This code seems to be looking for a specific item so don't bother to enumerate
        var criteria = source.FirstOrDefault(i => i.Key == "Report Criteria");
        if (String.IsNullOrEmpty(criteria.Key))
            return source;
    
        var lines = criteria.Value.Split(new [] { "\r\n" }, StringSplitOptions.None);
    
        //TODO: The existing code didn't look correct at all.  It was getting the current key and the type of the value and adding them to the list
        //for each line but doing nothing with the lines.
        return from line in lines
                select new KeyValuePair<string, string>(criteria.Key, line);
    }

    • Proposed as answer by Kristin Xie Tuesday, March 15, 2016 1:55 AM
    • Marked as answer by Kristin Xie Tuesday, March 15, 2016 2:06 AM
    Friday, March 4, 2016 6:04 PM
  • Notice what I am passing rebuildReportCriteria

    www.helixpoint.com

    Monday, March 7, 2016 6:19 PM
  • Yes I noticed it, but based upon your code it isn't accurate.  You are clearly working with KeyValuePair and therefore the 1.x interface is doing nothing that the generic version won't provide you already, with a lot less casting and errors.  Please post an example of how you're calling this method and any related type information so we can focus in on what you are needing.
    Monday, March 7, 2016 6:46 PM
  • var rx1 = (IEnumerable)rebuildReportCriteria(((IEnumerable)e.Current).GetEnumerator());

    www.helixpoint.com

    Thursday, March 10, 2016 7:04 PM
  • That's the code but it doesn't specify the type you're using.  It is nothing but a bunch of redundant casts.  What is the exact type of e as it is declared in your code either as a parameter or local variable.  You can mouse over e and get this information as well.
    Thursday, March 10, 2016 7:09 PM
  • 
    Csla.Data.SafeDataReader


    www.helixpoint.com

    Tuesday, March 15, 2016 3:00 PM
  • That isn't possible.  SafeDataReader is an IDataReader.  It doesn't implement IEnumerable and therefore the runtime cast would throw an exception.  There isn't a concept of Current with a data reader.  If you had that type then you would be enumerating a KeyValuePair either because the DB wouldn't return back that type.

    Tuesday, March 15, 2016 3:41 PM
  • Well My code works till the point that I need to convert and pass it back. You are saying there is no way to do this?

    www.helixpoint.com

    Tuesday, March 15, 2016 4:58 PM
  • I'm saying that at the point you hit this line of code:

    ((IEnumerable)e.Current)

    then you will get a runtime exception if it is a Safe.DataReader.  If e itself was a Safe.DataReader then it shouldn't even compile because there is no Current property.  Note that I'm basing this on the version that is currently in Github.  If you're using a different version then it might support the aforementioned features.

    Put a breakpoint on the call to your method. When the breakpoint is hit, hover over e and Current and determine the types of each of them. Then step into your method. If it crashes at that point then the value isn't convertible. If it steps into your code then check the parameter values.

    Tuesday, March 15, 2016 5:13 PM
  • Well My code works till the point that I need to convert and pass it back. You are saying there is no way to do this?

    www.helixpoint.com

    Still not entirely sure what you are expecting to do!

    You say it "works to a point", but from your latest info it looks like you are trying to cast an object into an entirely different kind of object and expect it to magically "work" (for some definition of "work").

    I'm actually surprised that the syntax checker/compiler lets you get away with it, but there seems to be a slight hole somewhere with casting to an interface (?).

    SafeDataReader only implements IDataReader. You are fooling C# into casting that into IEnumerable. But just because the compiler lets you get away with the cast, doesn't mean it makes any sense.

    In other words, if you have an ICow and cast it into an IBanana, the compiler might let you get away it, but horrible things will happen when you try to peel it!

    Lets go back to the beginning - what are you trying to do with your SafeDataReader object?

    Tuesday, March 15, 2016 5:16 PM
  • Apparently CSLA does. e is a "
    e = {Csla.Data.SafeDataReaderRowEnumerable}


    www.helixpoint.com

    Tuesday, March 15, 2016 5:42 PM
  • SafeDataReader is not a SafeDataReaderRowEnumerable so the original statement is still correct.  I cannot find such a type listed over at CSLA.NET at all. Is it an extension or custom type that you created?

    Nevertheless if you follow the definition it will likely be implementing IEnumerable. But you are treating everything as IEnumerable<KeyValuePair> so, assuming that assumption is correct, you get rid of the casts by simply doing this:

    e.OfType<KeyValuePair<...>>()

    which would return an IEnumerable<KeyValuePair<...>> which is what you are casting to. You could then eliminate all your casts.  This is a best guess estimate since I don't know the formal definition of SafeDataReaderRowEnumerable.

    Tuesday, March 15, 2016 5:58 PM
  • I have to pull out some data in e which in a list of field names that are separated with a line feed. I need to break them up and return them so I can move threw them with :

    
    for (int j = 0; rx.MoveNext(); j++)
    				{
    	bject v = ((KeyValuePair<string, object>)rx.Current).Value;
    .
    .
    .
    .


    www.helixpoint.com

    Tuesday, March 15, 2016 6:02 PM