Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7728747
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 1, 20262026-06-01T05:47:47+00:00 2026-06-01T05:47:47+00:00

I have an interface IRenderable and a class that manages rendering all instances of

  • 0

I have an interface IRenderable and a class that manages rendering all instances of classes implementing the interface.

I have many classes in my code and will expect others to create classes that implement the same interface.

Due to the nature of rendering I want to say things like “Draw instances of this class before instances of this class”.

The typical approach is to have every class implement a DrawOrder property, however I dislike this because classes don’t have a definite draw order value, it’s the relative order that matters. If I gave every class a DrawOrder property anyone implementing the interface would need to know what the values of all classes were. Obviously this isn’t possible if many people could implement their own class.


What I’d like is to be able to define rules that say “ClassA before ClassB, ClassC before ClassA”, then when working out the draw order / adding instances I could infer a correct drawing order. Others implementing the interface could add their own rules relating to built in implementations and their own additions.


EDIT: What I’m hoping for is some class that manages the rules and manages maintaining an order, something like below:

class Renderer
{
    private List<Rule> Rules;

    private List<IRenderable> Renderables;

    // Adds to list of rules
    void EnforceBefore(Type FirstClass, Type SecondClass);

    // Inserts items ensuring all rules are followed.
    void Insert(IRenderable ClassInstance);

    void RenderAll();
}

Classes could then add rules as appropriate (or I could have an interface method that returns them).

Below is a quick test that doesn’t work

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        List<string> MyList = new List<string> { "wherever", "second", "first", "third", "first", "third", "second" };

        RuleBasedComparer<string> RuleComparer = new RuleBasedComparer<string>();

        // I want to ensure all instances of "first" appear in the list before all instances of "second"
        // and all instances of "second" appear in the list before all instances of "third".
        // I don't care where "wherever" appears (or anything beyond the above rules)

        RuleComparer.AddRule("first", "second");
        RuleComparer.AddRule("second", "third");

        MyList.Sort(RuleComparer);

        foreach (var item in MyList)
            Console.WriteLine(item);
        Console.ReadKey();
    }
}

public class RuleBasedComparer<T> : Comparer<T>
{
    private class OrderRule
    {
        public readonly T Before;
        public readonly T After;

        public OrderRule(T before, T after)
        {
            Before = before;
            After = after;
        }
    }

    private List<OrderRule> _Rules = new List<OrderRule>();

    public void AddRule(T before, T after)
    {
        _Rules.Add(new OrderRule(before, after));
    }

    public override int Compare(T x, T y)
    {
        // Find the applicable rule for this pair (if any)
        var ApplicableRule = _Rules.Where(or => or.After.Equals(x) && or.Before.Equals(y) ||
                                                or.After.Equals(y) && or.Before.Equals(x)).SingleOrDefault();

        if (ApplicableRule != null)
        {
            // If there is a rule then if x should be before y then return -1, otherwise return 1
            if (ApplicableRule.Before.Equals(x))
                return -1;
            else
                return 1;
        }
        else
        {
            // If no rule exists then say they are equal
            return 0;
        }
    }
}

TL;DR: How do I go from rules that say things like “ClassA before ClassB” to a definite ordering of instances/classes.
Ambiguities created by a lack of complete rules shouldn’t matter, I just want the existing rules adhered to.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-01T05:47:49+00:00Added an answer on June 1, 2026 at 5:47 am

    I’ve managed to figure out a method that seems to work (complete code example below).

    Basically I add my rules, then I assign everything included in a rule with a possible ordering by inserting them into a list one by one, observing the rules as I add each one. The position of the item in the list becomes the ordering. When comparing 2 things in the list (not in a rule) I just return 0.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    class Program
    {
        static void Main(string[] args)
        {
            List<string> MyList = new List<string> { "second", "first", "second2", "wherever", "third", "second2", "third", "second", "first" };
    
            RuleBasedComparer<string> RuleComparer = new RuleBasedComparer<string>();
    
            // I want to ensure all instances of "first" appear in the list before all instances of "second" and "second2"
            // and all instances of "second" and "second2" appear in the list before all instances of "third".
            // I don't care where "wherever" appears (or anything beyond the above rules)
    
            RuleComparer.AddRule("first", "second");
            RuleComparer.AddRule("first", "second2");
            RuleComparer.AddRule("second", "third");
            RuleComparer.AddRule("second2", "third");
    
            MyList.Sort(RuleComparer);
    
            foreach (var item in MyList)
                Console.WriteLine(item);
            Console.ReadKey();
        }
    }
    
    public class RuleBasedComparer<T> : Comparer<T>
    {
        private class OrderRule
        {
            public readonly T Before;
            public readonly T After;
    
            public OrderRule(T before, T after)
            {
                Before = before;
                After = after;
            }
        }
    
        private List<OrderRule> _Rules = new List<OrderRule>();
    
        private List<T> DesiredOrdering = new List<T>();
    
        private bool _NeedToCalculateOrdering = true;
    
        public void AddRule(T before, T after)
        {
            if (!_NeedToCalculateOrdering)
                throw new InvalidOperationException("Cannot add rules once this comparer has.");
    
            _Rules.Add(new OrderRule(before, after));
        }
    
        private void CalculateOrdering()
        {
            _NeedToCalculateOrdering = false;
    
            var ItemsToOrder = _Rules.SelectMany(r => new[] { r.Before, r.After }).Distinct();
    
    
            foreach (var ItemToOrder in ItemsToOrder)
            {
                var MinIndex = 0;
                var MaxIndex = DesiredOrdering.Count;
    
                foreach (var Rule in _Rules.Where(r => r.Before.Equals(ItemToOrder)))
                {
                    var indexofAfter = DesiredOrdering.IndexOf(Rule.After);
    
                    if (indexofAfter != -1)
                    {
                        MaxIndex = Math.Min(MaxIndex, indexofAfter);
                    }
                }
    
                foreach (var Rule in _Rules.Where(r => r.After.Equals(ItemToOrder)))
                {
                    var indexofBefore = DesiredOrdering.IndexOf(Rule.Before);
    
                    if (indexofBefore != -1)
                    {
                        MinIndex = Math.Max(MinIndex, indexofBefore + 1);
                    }
                }
    
                if (MinIndex > MaxIndex)
                    throw new InvalidOperationException("Invalid combination of rules found!");
    
                DesiredOrdering.Insert(MinIndex, ItemToOrder);
            }
        }
    
        public override int Compare(T x, T y)
        {
            if (_NeedToCalculateOrdering)
                CalculateOrdering();
    
            if (x == null && y != null)
            {
                return -1;
            }
            else if (x != null && y == null)
                return 1;
            else if (x == null && y == null)
                return 0;
    
            // Find the applicable rule for this pair (if any)
            var IndexOfX = DesiredOrdering.IndexOf(x);
            var IndexOfY = DesiredOrdering.IndexOf(y);
    
            if (IndexOfX != -1 && IndexOfY != -1)
            {
                // We have a definite order
                if (IndexOfX > IndexOfY)
                    return 1;
                else if (IndexOfX < IndexOfY)
                    return -1;
                else
                    return 0;
            }
            else if (IndexOfX != -1)
            {
                return -1;
            }
            else if (IndexOfY != -1)
            {
                return 1;
            }
            else
            {
                return 0; // Or maybe compare x to y directly
                //return Comparer<T>.Default.Compare(x, y);
            }
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

We have an interface which will be implemented by classes that take care of
I have interface IModule and several classes that implements it. In test i need
If I have interface IFoo, and have several classes that implement it, what is
I have seen that if I have interface named interfaceABC. Example: public class ABController
I have interface IDoc and an abstract class that implements it named Doc. I
I have: interface IEntry {} class Entry : IEntry {} Why is it that
I have interface IConfigurationSource { .... } and class FileConfigurationSource : IConfigurationSource { FileConfigurationSource(string
I have interface Foo public interface Foo { public void test(); } Class FooChild
Let's say we have interface window_creator that responsible for creation of windows. For simplicity
I have an interface that has large numbers of controls, see image below. Interface

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.