Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

C#

Options
  • 07-07-2020 11:44pm
    #1
    Moderators, Computer Games Moderators, Social & Fun Moderators Posts: 80,003 Mod ✭✭✭✭


    For anyone that programs in C#, what would be the equivalent of the List.of method in java be in C#?

    List<Library>library = List.of();
    


«1

Comments

  • Registered Users Posts: 14,715 ✭✭✭✭Earthhorse


    I program in c# not Java so I don't know what List.of() is.

    I did a quick Google there but couldn't find any results.

    What does the List.of() method do?

    What is it that you're trying to achieve?


  • Registered Users Posts: 2,145 ✭✭✭dazberry


    Earthhorse wrote: »
    I did a quick Google there but couldn't find any results.
    The List.of() static factory methods provide a convenient way to create immutable lists. The List instances created by these methods have the following characteristics:

    They are structurally immutable. Elements cannot be added, removed, or replaced. Calling any mutator method will always cause UnsupportedOperationException to be thrown. However, if the contained elements are themselves mutable, this may cause the List's contents to appear to change.
    They disallow null elements. Attempts to create them with null elements result in NullPointerException.
    They are serializable if all elements are serializable.
    The order of elements in the list is the same as the order of the provided arguments, or of the elements in the provided array.
    They are value-based. Callers should make no assumptions about the identity of the returned instances. Factories are free to create new instances or reuse existing ones. Therefore, identity-sensitive operations on these instances (reference equality (==), identity hash code, and synchronization) are unreliable and should be avoided.
    They are serialized as specified on the Serialized Form page.


    I don't think there's anything 100% equivalent, the nearest probably is
      .AsReadOnly() to return a read only collection over the original list. However that does not expose any mutator methods.


  • Registered Users Posts: 2,015 ✭✭✭Colonel Panic


    C# has immutable collections if that's what you're after. The language handles immutability differently from Java.


  • Moderators, Computer Games Moderators, Social & Fun Moderators Posts: 80,003 Mod ✭✭✭✭Sephiroth_dude


    Thanks for the replies lads, just wondering how would I do something like this in C#
    List<Library>library = List.of(
    			new Library("American God","Neil Gaimen",1,Genre.URBANFANTASY,Stock.INSTOCK),
    			new Library("NeverWhere", "Neil Gaimen", 0,Genre.URBANFANTASY,Stock.OUTOFSTOCK),
    			new Library("IT", "Stephen King", 0, Genre.HORROR,Stock.OUTOFSTOCK),
    			new Library("The Dark Tower","Stephen King",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("Lord of the Ring, The FellowShip of the ring","J.R.R Tolkien",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("Harry Potter and the Philospher's Stone","J.K. Rowlin",3,Genre.FANTASY,Stock.INSTOCK),
    			new Library("Lord of the Rings,The Two Towers","J.R.R Tolkien",0,Genre.FANTASY,Stock.OUTOFSTOCK),
    			new Library("Lord of the Rings,The return of the King","J.R.R Tolkien",0,Genre.FANTASY,Stock.OUTOFSTOCK),
    			new Library("The Hobbit","J.R.R Tolkien",2,Genre.FANTASY,Stock.INSTOCK),
    			new Library("The Wheel Of Time","Robert Jordan",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("The Game Of Thrones","George R.R.Martin",0,Genre.HIGHFANTASY,Stock.OUTOFSTOCK),
    			new Library("The Name Of the Wind","Patrick Rothfuss",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("The Wise Man's Fear","Patrick Rothfuss",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("Carrie","Stephen King",3,Genre.HORROR,Stock.INSTOCK),
    			new Library("Salem's Lot","Stephen King",1,Genre.HORROR,Stock.INSTOCK));
    


  • Registered Users Posts: 11,977 ✭✭✭✭Giblet


    To just create a list, use the following. If you need an immutable list, there are other collection types which can be used.
    var library = new List<Library>(){
    			new Library("American God","Neil Gaimen",1,Genre.URBANFANTASY,Stock.INSTOCK),
    			new Library("NeverWhere", "Neil Gaimen", 0,Genre.URBANFANTASY,Stock.OUTOFSTOCK),
    			new Library("IT", "Stephen King", 0, Genre.HORROR,Stock.OUTOFSTOCK),
    			new Library("The Dark Tower","Stephen King",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("Lord of the Ring, The FellowShip of the ring","J.R.R Tolkien",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("Harry Potter and the Philospher's Stone","J.K. Rowlin",3,Genre.FANTASY,Stock.INSTOCK),
    			new Library("Lord of the Rings,The Two Towers","J.R.R Tolkien",0,Genre.FANTASY,Stock.OUTOFSTOCK),
    			new Library("Lord of the Rings,The return of the King","J.R.R Tolkien",0,Genre.FANTASY,Stock.OUTOFSTOCK),
    			new Library("The Hobbit","J.R.R Tolkien",2,Genre.FANTASY,Stock.INSTOCK),
    			new Library("The Wheel Of Time","Robert Jordan",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("The Game Of Thrones","George R.R.Martin",0,Genre.HIGHFANTASY,Stock.OUTOFSTOCK),
    			new Library("The Name Of the Wind","Patrick Rothfuss",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("The Wise Man's Fear","Patrick Rothfuss",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("Carrie","Stephen King",3,Genre.HORROR,Stock.INSTOCK),
    			new Library("Salem's Lot","Stephen King",1,Genre.HORROR,Stock.INSTOCK)};
    


  • Advertisement
  • Moderators, Computer Games Moderators, Social & Fun Moderators Posts: 80,003 Mod ✭✭✭✭Sephiroth_dude


    Thanks G, how do you mean immutable list? And what other collection types are there?


  • Registered Users Posts: 2,015 ✭✭✭Colonel Panic


    Immutable lists can't be changed once they've been created. Other collection types include Dictionary, Queue, Stack as well as concurrent and immutable variants.


  • Registered Users Posts: 4,833 ✭✭✭shootermacg


    If it's just a list you want,
    Edit ImmutableList will create an ImmutableList for you given an enumerable.

    immutableList = immutableList.Add(yourList);

    https://docs.microsoft.com/en-us/dotnet/api/system.collections.immutable.immutablelist-1?redirectedfrom=MSDN&view=netcore-3.1

    Thanks for the replies lads, just wondering how would I do something like this in C#
    var library = new List<Library>
    {
    			new Library("American God","Neil Gaimen",1,Genre.URBANFANTASY,Stock.INSTOCK),
    			new Library("NeverWhere", "Neil Gaimen", 0,Genre.URBANFANTASY,Stock.OUTOFSTOCK),
    			new Library("IT", "Stephen King", 0, Genre.HORROR,Stock.OUTOFSTOCK),
    			new Library("The Dark Tower","Stephen King",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("Lord of the Ring, The FellowShip of the ring","J.R.R Tolkien",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("Harry Potter and the Philospher's Stone","J.K. Rowlin",3,Genre.FANTASY,Stock.INSTOCK),
    			new Library("Lord of the Rings,The Two Towers","J.R.R Tolkien",0,Genre.FANTASY,Stock.OUTOFSTOCK),
    			new Library("Lord of the Rings,The return of the King","J.R.R Tolkien",0,Genre.FANTASY,Stock.OUTOFSTOCK),
    			new Library("The Hobbit","J.R.R Tolkien",2,Genre.FANTASY,Stock.INSTOCK),
    			new Library("The Wheel Of Time","Robert Jordan",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("The Game Of Thrones","George R.R.Martin",0,Genre.HIGHFANTASY,Stock.OUTOFSTOCK),
    			new Library("The Name Of the Wind","Patrick Rothfuss",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("The Wise Man's Fear","Patrick Rothfuss",1,Genre.FANTASY,Stock.INSTOCK),
    			new Library("Carrie","Stephen King",3,Genre.HORROR,Stock.INSTOCK),
    			new Library("Salem's Lot","Stephen King",1,Genre.HORROR,Stock.INSTOCK)
    };
    


  • Moderators, Computer Games Moderators, Social & Fun Moderators Posts: 80,003 Mod ✭✭✭✭Sephiroth_dude


    What am I doing wrong here lads, why won't it print out the list of books?

    public class Library
        {
            private String AuthorName { get; set; }
            private String BookName { get; set; }
            private int NumberOfCopies { get; set; }
            public Genre genre;
            public Stock stock;
    
            public Library(String AuthorNmae,String BookName,int NumberOfCopies,Genre genre,Stock stock)
            {
                this.AuthorName = AuthorName;
                this.BookName = BookName;
                this.NumberOfCopies = NumberOfCopies;
                this.genre = genre;
                this.stock = stock;
            }
    
            public String toString()
            {
                return ("Author Name: " + AuthorName + 
                        "\n"
                        +"Book Title: " + BookName + 
                        "\n" 
                        +"Number of Copies: " + NumberOfCopies + 
                        "\n"
                        +"Genre: " + genre +
                        "\n"
                        +"Stock: " + stock +
                        "\n"
                        );
            }
        }
    
        public enum Stock
        {
            INSTOCK,OUTOFSTOCK
        }
    
        public enum Genre
        {
            FANTASY,HIGHFANTASY,HORROR,URBANFANTASY
        }
    }
    

    public static void Main(string[] args)
            {
                var library = new List<Library>()
                {
                    new Library("Neil Gaimen","American God",2,Genre.URBANFANTASY,Stock.INSTOCK),
                    new Library("Neil Gaimen","NeverWhere",0,Genre.URBANFANTASY,Stock.OUTOFSTOCK),
    
                };
    
                List<Library> lib = new List<Library>();
                foreach(Library libb in library)
                {
                    Console.WriteLine(libb);
                }
            }
        }
    }
    

    Its just printing out the memory address I think.


  • Registered Users Posts: 14,715 ✭✭✭✭Earthhorse


    It's probably printing the type.

    I think your toString method needs to be ToString.

    In c# method names are PascalCase. Local variables should be camelCase.

    But the former is the only one affecting execution because you haven’t overwritten the default ToString method. If that's deliberate you should write:

    Console.WriteLine(libb.toString())

    But you should then consider renaming the method e.g. to ToDisplayName or something.


  • Advertisement
  • Moderators, Computer Games Moderators, Social & Fun Moderators Posts: 80,003 Mod ✭✭✭✭Sephiroth_dude


    Earthhorse wrote: »
    It's probably printing the type.

    I think your toString method needs to be ToString.

    In c# method names are PascalCase. Local variables should be camelCase.

    But the former is the only one affecting execution because you haven’t overwritten the default ToString method. If that's deliberate you should write:

    Console.WriteLine(libb.toString())

    But you should then consider renaming the method e.g. to ToDisplayName or something.

    Thanks that worked.

    You mean rename the ToString method is it?


  • Registered Users Posts: 14,715 ✭✭✭✭Earthhorse


    Yes. You probably don't want to do that though, I'm just outlining the option.


  • Registered Users Posts: 2,015 ✭✭✭Colonel Panic


    public override string ToString() { /* stuff here */ }
    

    Then you can use WriteLine without ToString etc.

    This is standard practice in .Net, Debuggers even use it.

    Don't use camelCase for C# method names please.


  • Registered Users Posts: 11,977 ✭✭✭✭Giblet


    You need to override ToString
    public override string ToString()
    {
    }  
    


  • Moderators, Computer Games Moderators, Social & Fun Moderators Posts: 80,003 Mod ✭✭✭✭Sephiroth_dude


    public override string ToString() { /* stuff here */ }
    

    Then you can use WriteLine without ToString etc.

    This is standard practice in .Net, Debuggers even use it.

    Don't use camelCase for C# method names please.

    Its camelCase in Java, I just assumed it was the same in C# 🤣


  • Registered Users Posts: 4,833 ✭✭✭shootermacg


    The better option in most cases for data, IMO, would be to use a specialized library. You get a nicely formatted readout of your object state, which you can direct to whatever output you decide on.

    https://www.newtonsoft.com/json
    Product product = new Product();
    product.Name = "Apple";
    product.Expiry = new DateTime(2008, 12, 28);
    product.Sizes = new string[] { "Small" };
    
    string json = JsonConvert.SerializeObject(product);
    

    Not only is it separating out concerns, but you can use it any any level meaning, you can print a list without the actual objects needing to concern themselves with details.
    You also get to add attributes like [JsonIgnore] to properties of your class that you don't want printed etc.
    I think a good rule of thumb would be to keep data related objects as simple as possible, offloading any additional functionality to separate classes.


  • Registered Users Posts: 2,015 ✭✭✭Colonel Panic


    Overriding ToString on data classes is still worth doing for debugging, logging, all sorts. It's not the same thing as serialisation.


  • Moderators, Computer Games Moderators, Social & Fun Moderators Posts: 80,003 Mod ✭✭✭✭Sephiroth_dude


    Is the convention in C# for constants the same as in java? all capitals with underscore between words.

    private const int MAX_NUMBER_OF_COPIES = 2;
    


  • Registered Users Posts: 14,715 ✭✭✭✭Earthhorse


    It's PascalCase:

    https://stackoverflow.com/questions/242534/c-sharp-naming-convention-for-constants

    Though I've often seen the Java style in use too.

    If you're on a team then use whatever convention they do if you're working on your own I'd recommend going with PascalCase.


  • Moderators, Computer Games Moderators, Social & Fun Moderators Posts: 80,003 Mod ✭✭✭✭Sephiroth_dude


    Hoping someone here might be able to help, If wanted to search through the list of books

    List<Library> library = new List<Library>() {
              new Library("Neil Gaimen","American Gods",1,Genre.URBANFANTASY,Stock.INSTOCK),
              new Library("Neil Gaimen","NeverWhere",0,Genre.URBANFANTASY,Stock.OUTOFSTOCK),
              new Library("Stephen King","I.T",1,Genre.HORROR,Stock.INSTOCK),
              new Library("Stephen King","Salems Lot",0,Genre.HORROR,Stock.INSTOCK),
              new Library("Stephen King","Carrie",1,Genre.HORROR,Stock.INSTOCK)
    
            };
    

    To see if a specific book is there, Is there a cleaner way to do than the way I have ? at the moment when I enter a authors name and the title it will tell that "Neil Gaimen " " American God " is there but for the rest in the list it return "Book not found". Here is the seach function and input function, Is there a cleaner way to search for them?
    public void SearchForBooks()
            {
                Console.WriteLine("Please enter autors name: ");
                string name = Console.ReadLine();
    
                Console.WriteLine("Please enter title name: ");
                string title = Console.ReadLine();
    
                CheckIfBookExists(name,title);
    
                if(CheckIfBookExists(name,title) == true)
                {
                    Console.WriteLine("BOOK FOUND! ");
                }
                else
                {
                    Console.WriteLine("BOOK NOT FOUND");
                }
    
                
            }
    
            public Boolean CheckIfBookExists(string name,string title)
            {
                foreach(Library lib in library)
                {
                    if(lib.AuthorName.Equals(name) && lib.BookName.Equals(title))
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                return true;
            }
    


  • Advertisement
  • Registered Users Posts: 4,833 ✭✭✭shootermacg


    Bit early for me today, so I am going to refer you to linq. it is very easy to use linq to query, split etc any collection.

    Linq is what makes c# so good when dealing with collections

    You can use various ways:

    return (yourList.Any(lib => lib.AuthorName.Equals(name) && lib.BookName.Equals(title)))

    or

    return yourList.Count(lib => lib.AuthorName.Equals(name) && lib.BookName.Equals(title)) >= 1

    or

    return (yourList.FirstOrDefault(lib => lib.AuthorName.Equals(name) && lib.BookName.Equals(title)) != null)


  • Registered Users Posts: 4,833 ✭✭✭shootermacg


    Please note, this isn't how I would do it myself, because querying collection etc doesn't require specific methods, but I did this to introduce you to 3 concepts, string comparison, extension methods, and linq.
    I didn't run this, I just typed it out, but it should work. Learning more about these things would be great for you.

    Also a main concept these days in code is "Tell, don't ask!" Linq is great for that, you would tell the collection what to return, you aren't asking if it has stuff. This process will remove a lot of conditional logic from your code making it more reliable. Also look up SOLID principles. Also if your method returns a bool, then it is a question, so it's good to have a question type of name, DoesXExist etc.
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.CompilerServices;
    
    namespace TestingStuff
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Please enter autors name: ");
                string name = Console.ReadLine();
    
                Console.WriteLine("Please enter title name: ");
                string title = Console.ReadLine();
                
                Console.WriteLine(SearchForBooks(name, title);
    
    
    
            }
    
            
            public string SearchForBooks(string author, string book)
            {
                var library = new List<Library>{
                  new Library("Neil Gaimen","American Gods"),
                  new Library("Neil Gaimen","NeverWhere"),
                  new Library("Stephen King","I.T"),
                  new Library("Stephen King","Salems Lot"),
                  new Library("Stephen King","Carrie")
                };
    
              return library.Any(l => l.DoesBookExist(author, book)) ? "BOOK FOUND! " : "BOOK NOT FOUND";
    
            }
        }
    
        public class Library
        {
            public string AuthorName { get; set; }
    
            public string BookName { get; set }
    
            public Library(string author, string book)
            {
                AuthorName = author;
                BookName = book;
            }
        }
    
        public static class LibraryHelper
        {
            public static bool DoesBookExist(this Library lib, string name, string title)
            {
                return lib.BookName.Equals(name, StringComparison.OrdinalIgnoreCase) && lib.AuthorName.Equals(name, StringComparison.OrdinalIgnoreCase);
            }
        }
    }
    


  • Moderators, Computer Games Moderators, Social & Fun Moderators Posts: 80,003 Mod ✭✭✭✭Sephiroth_dude


    Cheers for that s, much appreciated!


  • Registered Users Posts: 2,015 ✭✭✭Colonel Panic


    You could use C# Local Functions to put the DoesBookExist closer to the call site where it's used.


  • Registered Users Posts: 4,833 ✭✭✭shootermacg


    You could use C# Local Functions to put the DoesBookExist closer to the call site where it's used.

    A local function isn't really unit testable, so I wouldn't really see myself using this type of function on a day to day basis.

    Searching a collection is trivial, which i hope I pointed out the link in the previous post.

    I pointed out that I wouldn't personally write it that way, but I introduced a useful idea, which is why i added it

    But in saying that, I wouldn't add a method to a class that is concerned with storing data. When you get further down the line, you'll start using ORMs, a good rule of thumb is, don't mix your data with your control. So I would never put methods in with my data.

    The main reason for this is, you don't need an interface for data objects, if they consist purely of data. Most control objects require an interface for unit testing and mocking purposes.

    But on top of that, if you're dealing with collections, it makes sense to keep your memory requirements as small as possible. Then of course there's serialization to consider.

    So to answer your question more concisely, never mix methods with your data, you can always extend the data object should you need to add view/formatting related attributes. I also wouldn't have added a constructor to the data class while we're at it. But I think to hit Sephiroth with all of the enterprise related concerns at this stage in his development would do him no favours.


  • Registered Users Posts: 2,015 ✭✭✭Colonel Panic


    If you test the function, you're testing the local function.

    At this point, they're used all over the ASP.Net Core codebase!


  • Moderators, Computer Games Moderators, Social & Fun Moderators Posts: 80,003 Mod ✭✭✭✭Sephiroth_dude


    Shooter is the below bit a lambda expression?
    return library.Any(l => l.DoesBookExist(author, book)) ? "BOOK FOUND! " : "BOOK NOT FOUND";
    


  • Registered Users Posts: 4,833 ✭✭✭shootermacg


    Nah, it's just a short-hand if else expression. Unless you mean this part

    (l => l.DoesBookExist(author, book)) that is indeed a lamda expression. You can use any letter to represent a single item in the sequence, I generally use l for library.

    => is something more or less meaning "such that"
    So it would read like any library such that doesbookexist() returns true. Any library that matches the condition will make 'Any()' return true.

    Linq is wonderful to use. say, you wanted to return all the books of an author, it'll be (you can just pipe a lot of linq functions together):
    var libraries = library.Where(l => l.Author.Trim().ToLower().Contains("partial author name")).Select(a => a.BookName);
    

    Good resource here:

    https://www.tutorialsteacher.com/linq/sample-linq-queries


  • Registered Users Posts: 1,547 ✭✭✭rock22


    Hoping someone here might be able to help, If wanted to search through the list of books
    ......

            public Boolean CheckIfBookExists(string name,string title)
            {
                foreach(Library lib in library)
                {
                    if(lib.AuthorName.Equals(name) && lib.BookName.Equals(title))
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                return true;
            }
    

    Your code is always returning a result, true or false, on the first iteration.

    You need to rewrite to return true if the item is found otherwise continue with the foreach loop (hint you could set a default variable to false before entering the foreach loop)


  • Advertisement
  • Moderators, Computer Games Moderators, Social & Fun Moderators Posts: 80,003 Mod ✭✭✭✭Sephiroth_dude


    rock22 wrote: »
    (hint you could set a default variable to false before entering the foreach loop)

    Would you mind showing me an example of what you mean?


Advertisement