Przekazywanie obiektu jako parametr

0

Czy ktoś mógłby mi wyjaśnić jak przekazuje się w C# obiekt jako parametr metody? Otrzymuję błąd w metodzie addProduct():" Cannot implicitly convert type"
Próbowałem z ref, sprawdzałem tutaj na forum i na SO. Oprócz tego jakieś dwie godziny własnego dłubania. Oczywiście również sprawdzałem ze string[], podobnie metoda zachowuje się z List<>.

Co robię źle?

class Cart
    {
        Cart[] productList = new Cart[3]; 
       
        public void addProduct(Product product)
        {
            productList = product;
        }

        public void printList()
        {
             //Not implemented yet
        }
    }

Chodzi mi dokładnie o metodę Addproduct(), która w PHP wygląda tak:

class Cart
{
	private $products = [];

	public function addProduct(Product $product)
	{
		$this->products[] = $product;
	}

	public function listProducts()
	{
		foreach ($this->products as $product) {
			echo $product->getName() . '<br>';
		}
	}
}
2
class Cart
{
	List<Product> productList = new List<Product>(); 

	public void addProduct(Product product)
	{
		productList.Add(product);
	}

	public void printList()
	{
		productList.ForEach(Console.WriteLine);

		lub
		
		productList.ForEach(x => Console.WriteLine(x.Name));

		lub
		
		foreach (var product in productList)
		{
			Console.WriteLine(product.Name); // name? czy co tam chcesz id?  
		}
	}
}
2

Zamień:

Cart[] productList = new Cart[3];

Na:

List<Product> productList = new List<Product>();

Dlaczego tak to wyjaśnią Ci byle artykuły z podstawami języka, które musisz posiąść. C# to nie PHP, na szczęście. :-)

2

Dzięki! A czy mógłbyś napisać jakby to wyglądało z tablicą?

Twój kod z tablicą w PHP także wydaje się bardzo dziwny, np: tutaj: $this->products[] = $product;, gdzie wygląda jakbyś zamieniał kolekcję na pojedynczy obiekt.
Przepisanie tego kodu C# na wersję tablicową nie ma sensu, bo jak przekroczysz zakres zaalokowanych elementów to nie ma jak zwiększyć kolekcji, dlatego lista jest lepszym rozwiązaniem.

1
public class Cart
{
    private const int _size = 5;
    private int _index = 0;
    private Product[] _productArray = new Product[_size]; 

    public void addProduct(Product product)
    {
        if (_index < _size)
        {
            _productArray[_index] = product;
            _index++;
            return;
        }

        throw new ArgumentOutOfRangeException("Cart is already full."); // albo coś innego zamiast wyjątku 
    }

    public void printArray()
    {
        foreach (var product in _productArray)
        {
            Console.WriteLine(product);
        }
    }
}
2

@WeiXiao: Własny wyjątek jest tam całkiem spoko. Zastanawiałem się czy nie zastąpić go wyjątkiem wbudowanym, który rzuca po prostu indeks poza zakresem tablicy ale własny komunikat jest ładniejszy:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _4p
{
    class Product
    {
        public override string ToString() => "Product";
    }

    class Card
    {
        private readonly Product[] products;

        public int Count { get; private set; }

        public Card(int size)
        {
            Count = 0;
            products = new Product[size];
        }

        public void Add(Product product)
        {
            if (Count < products.Length)
                products[Count++] = product;
            else
                throw new Exception("Card full!");
        }

        public void Print()
        {
            foreach (Product p in products)
            {
                Console.WriteLine(p.ToString());
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var card = new Card(2);
                card.Add(new Product());
                card.Add(new Product());
                card.Print();

                //  Tutaj poleci wyjątek, który złapiemy.
                card.Add(new Product());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

Nie mówiąc już o tym, że wersja tablicowa jest bez sensu, bo niepotrzebnie komplikuje proste rozwiązanie.

0

Dziękuję wszystkim za pomoc. Wygląda na to, że przykład w PHP jest nie bardzo reprezentatywny jeśli chodzi o programowanie obiektowe. Dzięki jeszcze raz.

Nie dam się wciągnąć w dyskusję o PHP. Są świetni programiści , którzy w nim programują i wiedzą bardzo dużo na jego temat. I niech tak zostanie. ;)

0

Program ostatecznie wygląda tak:

class Product
    {
        private string name;

        public string getName()
        {
            return name;
        }
        public Product(string name)
        {
            this.name = name;
        }
    }

class Cart
    {
        private List<object> productList = new List<object>();

        public void addProduct(Product product)
        {
            productList.Add(product.getName());
        }
        public void printList()
        {
            productList.ForEach(Console.WriteLine);
        }
    }

class Program
    {
        static void Main(string[] args)
        {
            //class declaration
            Cart cart = new Cart();
            Product product1 = new Product("laptop");
            Product product2 = new Product("kabel USB");

            //app's logic
            cart.addProduct(product1);
            cart.addProduct(product2);

            //result's printing
            cart.printList();

            Console.ReadKey();
        }
    }
2

Czemu piszesz tak strasznie dziwnie:

  • Dlaczego zamiast własności piszesz metody?
  • Dlaczego tworzysz List<object> zamiast List<Product>?
  • Dlaczego nie trzymasz się konwencji nazewniczej C#?
2

Tak jak @grzesiek51114 wspomniał, zamiast:

private string name;

public string getName()
{
    return name;
}

public Product(string name)
{
    this.name = name;
}

lepiej jest użyć tutaj property, czyli:

public string Name { get; private set; }

public Product(string name)
{
    Name = name;
}
1

Uff, po paru ciepłych słowach w kierunku kompilatora, to jednak okazało się, że Wy macie rację a nie ja.
Dziękuję za poświęcony czas.

class Product
    {
        public string Name { get; private set; }

        public Product(string name)
        {
            Name = name; 
        }
    }

 class Cart 
    {
        private List<Product> productList = new List<Product>();

        public void AddProduct(Product product)
        {
            productList.Add(product);
        }
        public void PrintList()
        {
            foreach (var p in productList)
            {
                Console.WriteLine(p.Name);
            }
        }
    }

class Program
    {
        static void Main(string[] args)
        {
            //class declaration
            Cart cart = new Cart();
            Product product1 = new Product("laptop");
            Product product2 = new Product("kabel USB");

            //app's logic
            cart.AddProduct(product1);
            cart.AddProduct(product2);

            //result's printing
            cart.PrintList();

            Console.ReadKey();
        }
0

Pozostała jeszcze kwestia trzeciego punktu, o którym wspominał @grzesiek51114

grzesiek51114 napisał(a):
  • Dlaczego nie trzymasz się konwencji nazewniczej C#?

Stosujemy tutaj notację PascalCase, a nie camelCase. Twoje metody powinny nazywać się tak:

public void AddProduct(Product product) {}
public void PrintList() {}

1 użytkowników online, w tym zalogowanych: 0, gości: 1